您的位置:首页 > 其它

【bzoj2588】Count on a tree 主席树

2017-02-22 14:01 411 查看
这题给人开了个新思路。

原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间。

此题若带修改怎么办?

若对某个点的权值做修改,则这个点的子树都会受影响,想到了dfs序上的树状数组加差分套权值线段树,感觉很劲啊。

update:

好吧,带修改的树上第K大:bzoj1146,确实有这么一种做法。

/**************************************************************
Problem: 2588
User: chad
Language: C++
Result: Accepted
Time:6236 ms
Memory:57688 kb
****************************************************************/

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<map>
#include<queue>
using namespace std;
#define mem1(i,j) memset(i,j,sizeof(i))
#define mem2(i,j) memcpy(i,j,sizeof(i))
#define LL long long
#define up(i,j,n) for(LL i=(j);i<=(n);i++)
#define FILE "dealing"
#define poi vec
#define eps 1e-10
#define db double
#define mid ((l+r)>>1)
const int maxn=102000,inf=1000000000,mod=1000000007;
int read(){
LL x=0,f=1,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
return f*x;
}
bool cmax(int& a,int b){return a<b?a=b,true:false;}
bool cmin(int& a,int b){return a>b?a=b,true:false;}
int n,m,L=1;
int fa[maxn][32],dep[maxn],v[maxn],t[maxn];
struct node{int y,next;}e[maxn<<1];int linkk[maxn<<1],len;
struct Node{int v,id;}a[maxn];
bool cmp(Node a,Node b){return a.v<b.v;}
bool cmp2(Node a,Node b){return a.id<b.id;}
void insert(int x,int y){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;}
int rt[2300000],cnt=0,sum[2300000],c[2300000][2];
int key=0;
void updata(int o){sum[o]=sum[c[o][1]]+sum[c[o][0]];}
void set(int& o,int x,int l,int r){
o=++cnt;
if(l==r){sum[o]=sum[x]+1;return;}
if(key>mid)c[o][0]=c[x][0],set(c[o][1],c[x][1],mid+1,r);
else c[o][1]=c[x][1],set(c[o][0],c[x][0],l,mid);
updata(o);
}
void dfs(int x){
key=v[x];set(rt[x],rt[fa[x][0]],1,L);
for(int i=linkk[x];i;i=e[i].next){
if(e[i].y==fa[x][0])continue;
fa[e[i].y][0]=x;
dep[e[i].y]=dep[x]+1;
dfs(e[i].y);
}
}
int lca(int x,int y){
if(dep[x]>dep[y])swap(x,y);
for(int i=28;i>=0;i--)if(dep[y]-dep[x]>=(1<<i))y=fa[y][i];
if(x==y)return x;
for(int i=28;i>=0;i--)if(fa[y][i]!=fa[x][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int q[10],val,bol[10]={0,1,1,-1,-1};
int query(int l,int r){
if(l==r)return t[l];
val=0;up(i,1,4)val+=bol[i]*sum[c[q[i]][0]];
//printf("%d %d %d %d\n",l,r,sum[q[1]]+sum[q[2]]-sum[q[3]]-sum[q[4]],0);
if(key>=val){
key-=val;
up(i,1,4)q[i]=c[q[i]][1];
return query(mid+1,r);}
else {
up(i,1,4)q[i]=c[q[i]][0];
return query(l,mid);
}
}
int getK(int x,int y,int k){
key=k;
q[1]=rt[x],q[2]=rt[y],q[3]=rt[k=lca(x,y)],q[4]=rt[fa[k][0]];
return query(1,L);
}
int main(){
//freopen(FILE".in","r",stdin);
//freopen(FILE".out","w",stdout);
n=read(),m=read();
up(i,1,n)a[i].v=read(),a[i].id=i;
up(i,1,n-1){
int x=read(),y=read();
insert(x,y);insert(y,x);
}
sort(a+1,a+n+1,cmp);
int j=1;
while(true){
t[L]=a[j].v;//离散权值的实际权值
v[a[j].id]=L;j++;//j节点的离散权值
if(j>n)break;
if(a[j].v!=a[j-1].v)L++;
}
sort(a+1,a+n+1,cmp2);
dfs(1);
for(int j=1;j<=30;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
int last=0;
while(m--){
int u=read(),v=read(),k=read();
u^=last;
if(m)printf("%d\n",last=getK(u,v,k-1));
else printf("%d",getK(u,v,k-1));
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: