樹上路徑帶修第k大問題,沒有強制在線。c++
主體思想:l[x]爲點x的dfs序,r[x]爲子樹x中最後一個節點的dfs序,sum[i]爲dfs序爲1~i的節點的某種和,d爲x,y的lca,則路徑x~y的和=sum[l[x]]+sum[l[y]]-sum[l[d]]-sum[l[fa[d]]]。單點修改是對子樹範圍差分即l[x]處+=w,r[x]+1處-=w。spa
這道題sum用主席樹維護,查詢時值域上二分便可。code
#include <bits/stdc++.h> #define trvl(x,i,y) for(int i=ehd[x],y; y=to[i],i; i=lst[i]) using namespace std; const int N=8e4+10; const int M=8e6+10; int n,m,T,a[N],b[N*2]; int ect,ehd[N],to[N*2],lst[N*2]; int cid,lid[N],rid[N],fa[N][20],dep[N]; int cnt,rt[N],siz[M],lc[M],rc[M]; void insert(int x,int y) { to[++ect]=y,lst[ect]=ehd[x],ehd[x]=ect; to[++ect]=x,lst[ect]=ehd[y],ehd[y]=ect; } void dfs(int x,int p) { lid[x]=++cid; dep[x]=dep[fa[x][0]=p]+1; for(int i=1; (1<<i)<=dep[x]; ++i) fa[x][i]=fa[fa[x][i-1]][i-1]; trvl(x,i,y) if(y!=p) dfs(y,x); rid[x]=cid; } int get_lca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); int dif=dep[x]-dep[y]; for(int i=19; ~i; --i) if((dif>>i)&1) x=fa[x][i]; if(x==y) return x; for(int i=19; ~i; --i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } void mdf(int&x,int l,int r,int p,int w) { if(!x) x=++cnt; siz[x]+=w; if(l==r) return; int mid=(l+r)>>1; if(p<=mid) mdf(lc[x],l,mid,p,w); else mdf(rc[x],mid+1,r,p,w); } void mdf(int x,int p,int w) { for(; x<=n; x+=x&-x) mdf(rt[x],1,T,p,w); } int top[2],d[2][N]; int kth(int l,int r,int k) { if(l==r) return l; int mid=(l+r)>>1,s=0; for(int i=1; i<=top[0]; ++i) s+=siz[lc[d[0][i]]]; for(int i=1; i<=top[1]; ++i) s-=siz[lc[d[1][i]]]; // printf("<%d,%d,%d> %d\n",l,r,k,s); if(k<=s) { for(int i=1; i<=top[0]; ++i) d[0][i]=lc[d[0][i]]; for(int i=1; i<=top[1]; ++i) d[1][i]=lc[d[1][i]]; return kth(l,mid,k); } else { for(int i=1; i<=top[0]; ++i) d[0][i]=rc[d[0][i]]; for(int i=1; i<=top[1]; ++i) d[1][i]=rc[d[1][i]]; return kth(mid+1,r,k-s); } } int qK[N],qA[N],qB[N]; int main() { scanf("%d%d",&n,&m); T=n; for(int i=1; i<=n; ++i) scanf("%d",a+i),b[i]=a[i]; for(int x,y,i=n; --i; ) scanf("%d%d",&x,&y),insert(x,y); for(int i=1; i<=m; ++i) { scanf("%d%d%d",qK+i,qA+i,qB+i); if(!qK[i]) b[++T]=qB[i]; } dfs(1,0); sort(b+1,b+T+1); T=unique(b+1,b+T+1)-b-1; for(int i=1; i<=n; ++i) { a[i]=lower_bound(b+1,b+T+1,a[i])-b; mdf(lid[i],a[i],1); mdf(rid[i]+1,a[i],-1); } for(int i=1; i<=m; ++i) { if(!qK[i]) { int x=qA[i]; mdf(lid[x],a[x],-1); mdf(rid[x]+1,a[x],1); a[x]=lower_bound(b+1,b+T+1,qB[i])-b; mdf(lid[x],a[x],1); mdf(rid[x]+1,a[x],-1); } else { top[0]=top[1]=0; int lca=get_lca(qA[i],qB[i]); // printf("%d,%d,%d,%d\n",qA[i],qB[i],lca,fa[lca][0]); for(int x=lid[qA[i]]; x; x-=x&-x) d[0][++top[0]]=rt[x]; for(int x=lid[qB[i]]; x; x-=x&-x) d[0][++top[0]]=rt[x]; for(int x=lid[lca]; x; x-=x&-x) d[1][++top[1]]=rt[x]; for(int x=lid[fa[lca][0]]; x; x-=x&-x) d[1][++top[1]]=rt[x]; int s=dep[qA[i]]+dep[qB[i]]-dep[lca]-dep[fa[lca][0]]; if(s<qK[i]) puts("invalid request!"); else printf("%d\n",b[kth(1,T,s-qK[i]+1)]); } } return 0; }