BZOJ
第一种方法,dfs序上建可持久化线段树,然后询问的时候把两点之间的所有树链扒出来做差。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 int hd[N],ne,n,n2,m,fa[N],son[N],siz[N],dep[N],top[N],dfn[N],rnk[N],tot,rt[N],ls[N*20],rs[N*20],val[N*20],tot2,a[N],b[N],ql[100],qr[100],nl,nr; 6 struct E {int v,nxt;} e[N<<1]; 7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;} 8 void dfs1(int u,int f,int d) { 9 fa[u]=f,son[u]=0,siz[u]=1,dep[u]=d; 10 for(int i=hd[u]; ~i; i=e[i].nxt) { 11 int v=e[i].v; 12 if(v==fa[u])continue; 13 dfs1(v,u,d+1),siz[u]+=siz[v]; 14 if(siz[v]>siz[son[u]])son[u]=v; 15 } 16 } 17 void dfs2(int u,int tp) { 18 top[u]=tp,dfn[u]=++tot,rnk[tot]=u; 19 if(son[u])dfs2(son[u],tp); 20 for(int i=hd[u]; ~i; i=e[i].nxt) { 21 int v=e[i].v; 22 if(v==fa[u]||v==son[u])continue; 23 dfs2(v,v); 24 } 25 } 26 #define mid ((l+r)>>1) 27 void upd(int& u,int v,int x,int l=1,int r=n2) { 28 if(!u)u=++tot2; 29 val[u]=val[v]+1; 30 if(l==r)return; 31 if(x<=mid)upd(ls[u],ls[v],x,l,mid),rs[u]=rs[v]; 32 else upd(rs[u],rs[v],x,mid+1,r),ls[u]=ls[v]; 33 } 34 int ask(int u,int v,int k) { 35 for(nl=nr=0; top[u]!=top[v]; u=fa[top[u]]) { 36 if(dep[top[u]]<dep[top[v]])swap(u,v); 37 ql[nl++]=rt[dfn[top[u]]-1],qr[nr++]=rt[dfn[u]]; 38 } 39 if(dep[u]<dep[v])swap(u,v); 40 ql[nl++]=rt[dfn[v]-1],qr[nr++]=rt[dfn[u]]; 41 int l=1,r=n2; 42 while(l<r) { 43 int cnt=0; 44 for(int i=0; i<nr; ++i)cnt+=val[ls[qr[i]]]; 45 for(int i=0; i<nl; ++i)cnt-=val[ls[ql[i]]]; 46 if(k<=cnt) { 47 for(int i=0; i<nr; ++i)qr[i]=ls[qr[i]]; 48 for(int i=0; i<nl; ++i)ql[i]=ls[ql[i]]; 49 r=mid; 50 } else { 51 k-=cnt; 52 for(int i=0; i<nr; ++i)qr[i]=rs[qr[i]]; 53 for(int i=0; i<nl; ++i)ql[i]=rs[ql[i]]; 54 l=mid+1; 55 } 56 } 57 return l; 58 } 59 int main() { 60 memset(hd,-1,sizeof hd),ne=0; 61 scanf("%d%d",&n,&m); 62 for(int i=1; i<=n; ++i)scanf("%d",&a[i]); 63 for(int i=1; i<=n; ++i)b[i-1]=a[i]; 64 sort(b,b+n),n2=unique(b,b+n)-b; 65 for(int i=1; i<=n; ++i)a[i]=(lower_bound(b,b+n2,a[i])-b)+1; 66 for(int i=1; i<n; ++i) { 67 int u,v; 68 scanf("%d%d",&u,&v); 69 addedge(u,v),addedge(v,u); 70 } 71 tot=0,dfs1(1,0,1),dfs2(1,1); 72 memset(rt,0,sizeof rt),tot2=0; 73 for(int i=1; i<=n; ++i)upd(rt[i],rt[i-1],a[rnk[i]],1,n2); 74 for(int last=0; m--;) { 75 int u,v,k; 76 scanf("%d%d%d",&u,&v,&k),u^=last; 77 int ans=b[ask(u,v,k)-1]; 78 printf("%d ",ans),last=ans; 79 } 80 return 0; 81 }
仔细一想这样似乎麻烦了点。因为没有修改操作,我们可以直接用子结点继承父节点的方式来建线段树,然后查询的时候,用u,v的线段树减去lca的线段树再减去lca父节点的线段树即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 int hd[N],ne,n,n2,m,fa[N],son[N],siz[N],dep[N],top[N],dfn[N],rnk[N],tot,rt[N],ls[N*20],rs[N*20],val[N*20],tot2,a[N],b[N],ql[100],qr[100],nl,nr; 6 struct E {int v,nxt;} e[N<<1]; 7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;} 8 void dfs1(int u,int f,int d) { 9 fa[u]=f,son[u]=0,siz[u]=1,dep[u]=d; 10 for(int i=hd[u]; ~i; i=e[i].nxt) { 11 int v=e[i].v; 12 if(v==fa[u])continue; 13 dfs1(v,u,d+1),siz[u]+=siz[v]; 14 if(siz[v]>siz[son[u]])son[u]=v; 15 } 16 } 17 void dfs2(int u,int tp) { 18 top[u]=tp,dfn[u]=++tot,rnk[tot]=u; 19 if(son[u])dfs2(son[u],tp); 20 for(int i=hd[u]; ~i; i=e[i].nxt) { 21 int v=e[i].v; 22 if(v==fa[u]||v==son[u])continue; 23 dfs2(v,v); 24 } 25 } 26 #define mid ((l+r)>>1) 27 void upd(int& u,int v,int x,int l=1,int r=n2) { 28 if(!u)u=++tot2; 29 val[u]=val[v]+1; 30 if(l==r)return; 31 if(x<=mid)upd(ls[u],ls[v],x,l,mid),rs[u]=rs[v]; 32 else upd(rs[u],rs[v],x,mid+1,r),ls[u]=ls[v]; 33 } 34 void dfs3(int u) { 35 upd(rt[u],rt[fa[u]],a[u]); 36 for(int i=hd[u]; ~i; i=e[i].nxt) { 37 int v=e[i].v; 38 if(v==fa[u])continue; 39 dfs3(v); 40 } 41 } 42 int lca(int u,int v) { 43 for(; top[u]!=top[v]; u=fa[top[u]])if(dep[top[u]]<dep[top[v]])swap(u,v); 44 return dep[u]<dep[v]?u:v; 45 } 46 int ask(int u,int v,int w1,int w2,int k,int l=1,int r=n2) { 47 if(l==r)return l; 48 int cnt=val[ls[u]]+val[ls[v]]-val[ls[w1]]-val[ls[w2]]; 49 return k<=cnt?ask(ls[u],ls[v],ls[w1],ls[w2],k,l,mid):ask(rs[u],rs[v],rs[w1],rs[w2],k-cnt,mid+1,r); 50 } 51 int main() { 52 memset(hd,-1,sizeof hd),ne=0; 53 scanf("%d%d",&n,&m); 54 for(int i=1; i<=n; ++i)scanf("%d",&a[i]); 55 for(int i=1; i<=n; ++i)b[i-1]=a[i]; 56 sort(b,b+n),n2=unique(b,b+n)-b; 57 for(int i=1; i<=n; ++i)a[i]=(lower_bound(b,b+n2,a[i])-b)+1; 58 for(int i=1; i<n; ++i) { 59 int u,v; 60 scanf("%d%d",&u,&v); 61 addedge(u,v),addedge(v,u); 62 } 63 tot=0,dfs1(1,0,1),dfs2(1,1); 64 memset(rt,0,sizeof rt),tot2=0; 65 dfs3(1); 66 for(int last=0; m--;) { 67 int u,v,k; 68 scanf("%d%d%d",&u,&v,&k),u^=last; 69 int w=lca(u,v); 70 int ans=b[ask(rt[u],rt[v],rt[w],rt[fa[w]],k)-1]; 71 printf("%d ",ans),last=ans; 72 } 73 return 0; 74 }