题解:
主席树+树状数组+树链剖分
树状数组维护修改
树链剖分维护树型结构
主席树维护持久化
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define lc(x) t[x].l #define rc(x) t[x].r typedef long long ll; const int N=8e4+5; int deep[N],fa[N],mx[N],size[N],top[N],tid[N],tot,L[N],R[N]; int A[N<<1],B[N<<1],a,b,crt[N],rt[N],sz,h[N],cnt,n,Q,w[N],u,v,k,mp[N<<1],m; struct node{int l,r,w;}t[N*128]; struct ques{int k,a,b;}q[N]; struct edge{int v,ne;}e[N<<1]; int ef(int v) { int l=1,r=m; while(l<r) { int mid=(l+r)/2; if (mp[mid]<v)l=mid+1; else r=mid; } return l; } void ins(int u,int v) { e[++cnt].v=v; e[cnt].ne=h[u]; h[u]=cnt; } void dfs(int u) { size[u]=1; for(int i=h[u];i;i=e[i].ne) { int v=e[i].v; if(v==fa[u]) continue; fa[v]=u;deep[v]=deep[u]+1; dfs(v); size[u]+=size[v]; if(size[v]>size[mx[u]]) mx[u]=v; } } void dfs(int u,int anc) { if(!u) return; tid[u]=L[u]=++tot; top[u]=anc; dfs(mx[u],anc); for (int i=h[u];i;i=e[i].ne) if (e[i].v!=fa[u]&&e[i].v!=mx[u]) dfs(e[i].v,e[i].v); R[u]=tot; } int lca(int x,int y) { while (top[x]!=top[y]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); x=fa[top[x]]; } if (tid[x]>tid[y]) swap(x,y); return x; } void ins(int &x,int l,int r,int p,int d) { t[++sz]=t[x];x=sz; t[x].w+=d; if (l==r) return; int mid=(l+r)>>1; if (p<=mid) ins(lc(x),l,mid,p,d); else ins(rc(x),mid+1,r,p,d); } void build(int u) { if (!u) return; rt[u]=rt[fa[u]]; ins(rt[u],1,m,w[u],1); build(mx[u]); for (int i=h[u];i;i=e[i].ne) if (e[i].v!=fa[u]&&e[i].v!=mx[u]) build(e[i].v); } void add(int x,int v,int d) { for (int i=x;i<=tot;i+=i&-i) ins(crt[i],1,m,v,d); } bool check(int k) { int suml=0,sumr=0; for (int i=1;i<=a;i++) suml+=t[A[i]].w; for (int i=1;i<=b;i++) sumr+=t[B[i]].w; return sumr-suml>=k; } int cal() { int suml=0,sumr=0; for (int i=1;i<=a;i++) suml+=t[rc(A[i])].w; for (int i=1;i<=b;i++) sumr+=t[rc(B[i])].w; return sumr-suml; } void query(int ql,int qr,int k) { a=b=0;int p=lca(ql,qr); B[++b]=rt[ql];B[++b]=rt[qr]; A[++a]=rt[p];A[++a]=rt[fa[p]]; for (int i=L[ql];i;i-=i&-i) B[++b]=crt[i]; for (int i=L[qr];i;i-=i&-i) B[++b]=crt[i]; for (int i=L[p];i;i-=i&-i) A[++a]=crt[i]; for (int i=L[fa[p]];i;i-=i&-i) A[++a]=crt[i]; if (!check(k)){puts("invalid request!");return;} int l=1,r=m; while (l<r) { int mid=(l+r)>>1,rsize=cal(); if (rsize>=k) { l=mid+1; for (int i=1;i<=a;i++) A[i]=rc(A[i]); for (int i=1;i<=b;i++) B[i]=rc(B[i]); } else { r=mid; k-=rsize; for (int i=1;i<=a;i++) A[i]=lc(A[i]); for (int i=1;i<=b;i++) B[i]=lc(B[i]); } } printf("%d\n",mp[l]); } int main() { scanf("%d%d",&n,&Q); for (int i=1;i<=n;i++)scanf("%d",&w[i]),mp[++m]=w[i]; for (int i=1;i<=n-1;i++)scanf("%d%d",&u,&v),ins(u,v),ins(v,u); dfs(1);dfs(1,1); for (int i=1;i<=Q;i++) { scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b); if (q[i].k==0) mp[++m]=q[i].b; } sort(mp+1,mp+1+m); int p=0;mp[++p]=mp[1]; for (int i=2;i<=m;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i]; m=p; for (int i=1;i<=n;i++) w[i]=ef(w[i]); build(1); for (int i=1;i<=Q;i++) { int k=q[i].k,a=q[i].a,b=q[i].b; if (k==0) { add(L[a],w[a],-1);add(R[a]+1,w[a],1); w[a]=ef(b); add(L[a],w[a],1);add(R[a]+1,w[a],-1); } else query(a,b,k); } return 0; }