【bzoj2588】Count on a tree 主席树
这题给人开了个新思路。
原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间。
此题若带修改怎么办?
若对某个点的权值做修改,则这个点的子树都会受影响,想到了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; }