BZOJ2588:LCA+主席树来实现树上两点之间第K大点权查询
对于每个节点维护这个节点到根的权值线段树
对于每个询问(x,y),这条路径上的线段树
tree[x]+tree[y]-tree[lca(x,y)]-tree[fa[lca(x,y)]]
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=100005; 5 const int maxm=2000005; 6 int n,m,tot,cnt,ind,sz,last; 7 int tmp[maxn],hash[maxn],g[maxn],v[maxn]; 8 int num[maxn],pos[maxn],deep[maxn]; 9 int sum[maxm],lch[maxm],rch[maxm]; 10 int root[maxn]; 11 int fa[maxn][17]; 12 struct Edge 13 { 14 int t,next; 15 }e[2*maxn]; 16 inline long long read() 17 { 18 long long x=0,f=1;char ch=getchar(); 19 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 20 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 21 return x*f; 22 } 23 //二分查找离散化之后的x的下标 24 int find(int x) 25 { 26 int l=1,r=tot; 27 while(l<=r) 28 { 29 int mid=(l+r)>>1; 30 if(hash[mid]<x) l=mid+1; 31 else if(hash[mid]==x) return mid; 32 else r=mid-1; 33 } 34 return l; 35 } 36 void insert(int u,int v) 37 { 38 cnt++; 39 e[cnt].t=v;e[cnt].next=g[u];g[u]=cnt; 40 cnt++; 41 e[cnt].t=u;e[cnt].next=g[v];g[v]=cnt; 42 } 43 void dfs(int x) 44 { 45 ind++;num[ind]=x;pos[x]=ind; 46 for(int i=1;i<=16;i++) 47 if((1<<i)<=deep[x]) fa[x][i]=fa[fa[x][i-1]][i-1]; 48 else break; 49 for(int tmp=g[x];tmp;tmp=e[tmp].next) 50 { 51 if(fa[x][0]!=e[tmp].t) 52 { 53 deep[e[tmp].t]=deep[x]+1; 54 fa[e[tmp].t][0]=x; 55 dfs(e[tmp].t); 56 } 57 } 58 } 59 void update(int l,int r,int x,int &y,int num) 60 { 61 y=++sz; 62 sum[y]=sum[x]+1; 63 if(l==r) return; 64 lch[y]=lch[x];rch[y]=rch[x]; 65 int mid=(l+r)>>1; 66 if(num<=mid) 67 update(l,mid,lch[x],lch[y],num); 68 else update(mid+1,r,rch[x],rch[y],num); 69 } 70 int lca(int x,int y) 71 { 72 if(deep[x]<deep[y]) swap(x,y); 73 int t=deep[x]-deep[y]; 74 for(int i=0;i<=16;i++) 75 if((1<<i)&t) x=fa[x][i]; 76 for(int i=16;i>=0;i--) 77 if(fa[x][i]!=fa[y][i]) 78 x=fa[x][i],y=fa[y][i]; 79 if(x==y) return x; 80 return fa[x][0]; 81 } 82 int query(int x,int y,int rk) 83 { 84 int a=x,b=y,c=lca(x,y),d=fa[c][0]; 85 a=root[pos[a]],b=root[pos[b]],c=root[pos[c]],d=root[pos[d]]; 86 int l=1,r=tot; 87 while(l<r) 88 { 89 int mid=(l+r)>>1; 90 int tmp=sum[lch[a]]+sum[lch[b]]-sum[lch[c]]-sum[lch[d]]; 91 if(tmp>=rk) r=mid,a=lch[a],b=lch[b],c=lch[c],d=lch[d]; 92 else rk-=tmp,l=mid+1,a=rch[a],b=rch[b],c=rch[c],d=rch[d]; 93 } 94 return hash[l]; 95 } 96 int main() 97 { 98 n=read();m=read(); 99 for(int i=1;i<=n;i++) 100 v[i]=read(),tmp[i]=v[i]; 101 sort(tmp+1,tmp+n+1); //点权排序 102 hash[++tot]=tmp[1]; 103 for(int i=2;i<=n;i++) 104 if(tmp[i]!=tmp[i-1]) 105 hash[++tot]=tmp[i]; 106 //离散化 107 for(int i=1;i<=n;i++) v[i]=find(v[i]); 108 //存位置,离散化 109 for(int i=1;i<n;i++) 110 { 111 int u,v; 112 u=read();v=read(); 113 insert(u,v); 114 } 115 dfs(1); 116 for(int i=1;i<=n;i++) 117 { 118 int t=num[i]; //树上点权 119 update(1,tot,root[pos[fa[t][0]]],root[i],v[t]);//建立主席树 120 } 121 for(int i=1;i<=m;i++) 122 { 123 int x=read(),y=read(),rk=read(); 124 x^=last; 125 last=query(x,y,rk); 126 printf("%d",last); 127 if(i!=m) printf("\n"); 128 } 129 return 0; 130 }