[lca][主席树] Jzoj P5850 e
题解
- 首先,对于一个最小联通块就是从每个点出发,到他们所有点公共的lca的所有链组成
- 那么我们就需要查询一条到祖先的链上的权值中r的前驱后继
- 然后就是主席树
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 const int mx=1e5+10,inf=1e9,inf1=2e9; 6 int n,q,type,cnt,ans,a[mx],T[mx],f[mx][20],dep[mx],head[mx],x[mx*3],L[mx*50],R[mx*50],sum[mx*50]; 7 struct edge{int to,from;}e[mx*2]; 8 void insert(int x,int y) { e[++cnt].to=y; e[cnt].from=head[x]; head[x]=cnt; } 9 void add(int &d,int x,int l,int r,int y,int k) 10 { 11 if (!d) d=++cnt; 12 sum[d]=sum[x]+k; 13 if (l==r) return; 14 int mid=(l+r)>>1; 15 if (y<=mid) R[d]=R[x],add(L[d],L[x],l,mid,y,k); else L[d]=L[x],add(R[d],R[x],mid+1,r,y,k); 16 } 17 void dfs(int x,int fa) 18 { 19 dep[x]=dep[fa]+1,f[x][0]=fa; 20 add(T[x],T[fa],1,inf,a[x],1); 21 for (int i=head[x];i;i=e[i].from) 22 if (e[i].to!=fa) 23 dfs(e[i].to,x); 24 } 25 int getlca(int x,int y) 26 { 27 if (dep[x]<dep[y]) swap(x,y); 28 for (int i=19;i>=0;i--) 29 if (dep[f[x][i]]>=dep[y]) 30 x=f[x][i]; 31 if (x==y) return x; 32 for (int i=19;i>=0;i--) 33 if (f[x][i]!=f[y][i]) 34 x=f[x][i],y=f[y][i]; 35 return f[x][0]; 36 } 37 int getpre(int x,int y,int l,int r,int d) 38 { 39 if (!(sum[x]-sum[y])) return 0; 40 if (l==r) return l; 41 int mid=(l+r)>>1,w; 42 if (d<=mid) return getpre(L[x],L[y],l,mid,d); 43 else 44 { 45 if ((w=getpre(R[x],R[y],mid+1,r,d))) return w; 46 return getpre(L[x],L[y],l,mid,d); 47 } 48 } 49 int getnxt(int x,int y,int l,int r,int d) 50 { 51 if (!(sum[x]-sum[y])) return 0; 52 if (l==r) return l; 53 int mid=(l+r)>>1,w; 54 if (d>mid) return getnxt(R[x],R[y],mid+1,r,d); 55 else 56 { 57 if ((w=getnxt(L[x],L[y],l,mid,d))) return w; 58 return getnxt(R[x],R[y],mid+1,r,d); 59 } 60 } 61 int main() 62 { 63 freopen("e.in","r",stdin); 64 freopen("e.out","w",stdout); 65 scanf("%d%d%d",&n,&q,&type); 66 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 67 for (int i=1;i<=n-1;i++) 68 { 69 int u,v; 70 scanf("%d%d",&u,&v); 71 insert(u,v),insert(v,u); 72 } 73 cnt=0,dfs(1,0); 74 for (int j=1;j<20;j++) 75 for (int i=1;i<=n;i++) 76 f[i][j]=f[f[i][j-1]][j-1]; 77 for (int i=1;i<=q;i++) 78 { 79 int r,k; 80 scanf("%d%d",&r,&k); 81 for (int j=1;j<=k;j++) 82 { 83 scanf("%d",&x[j]); 84 x[j]=(x[j]-1+ans*type)%n+1; 85 } 86 int lca=x[1]; 87 for (int j=2;j<=k;j++) lca=getlca(lca,x[j]); 88 lca=f[lca][0],ans=inf1; 89 for (int j=1;j<=k;j++) 90 { 91 int ans1=getpre(T[x[j]],T[lca],1,inf,r), 92 ans2=getnxt(T[x[j]],T[lca],1,inf,r); 93 if (ans1) ans=min(ans,r-ans1); 94 if (ans2) ans=min(ans,ans2-r); 95 } 96 printf("%d\n",ans); 97 } 98 }