这道题和bzoj2588很像,是动态区间第K大的变形。
先求DFS序,一棵子树的DFS是连续的,不妨记为[l,r],我们维护前缀和,在l处+1,在r+1处-1。
变成动态区间第K大的经典问题,用树状数组套线段树。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); inline int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } inline LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxN=80000; const int maxQ=80000; const int maxcnt=maxN+maxQ; int N,Q; int T[maxN+100]; int first[maxN+100],now; struct Tedge{int v,next;}edge[2*maxN+100]; struct Tdata{int k,a,b;inline void input(){k=gint();a=gint();b=gint();}}data[maxQ+100]; int bak[maxcnt+100],cnt; inline void addedge(int u,int v){now++;edge[now].v=v;edge[now].next=first[u];first[u]=now;} int g,idx[maxN+100],l[maxN+100],r[maxN+100]; int vis[maxN+100]; int top,sta[maxN+100],last[maxN+100]; int dep[maxN+100],fa[maxN+100],jump[31][maxN+100]; int head,tail,que[maxN+100]; inline void DFS() { int j; g=0; vis[sta[top=1]=1]=1; last[1]=first[1]; idx[1]=++g; fa[1]=0; dep[1]=1; jump[0][1]=1;re(j,1,30)jump[j][1]=jump[j-1][jump[j-1][1]]; while(top>=1) { int u=sta[top],&i=last[top],v; for(v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(!vis[v]) { vis[sta[++top]=v]=1; last[top]=first[v]; idx[v]=++g; fa[v]=u; dep[v]=dep[u]+1; jump[0][v]=u;re(j,1,30)jump[j][v]=jump[j-1][jump[j-1][v]]; break; } if(i==-1)top--; } mmst(vis,0); vis[que[head=tail=0]=1]=1; while(head<=tail) { int u=que[head++],i,v; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(!vis[v])vis[que[++tail]=v]=1; } red(j,tail,0) { int u=que[j],i,v; l[u]=r[u]=idx[u]; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(v!=jump[0][u])upmin(l[u],l[v]),upmax(r[u],r[v]); } } struct Tnode{int son[2],val;}sn[12000000];int cn; inline int newnode(){++cn;sn[cn].son[0]=sn[cn].son[1]=sn[cn].val=0;return cn;} inline void update(int p,int l,int r,int x,int val) { while(l<=r) { sn[p].val+=val; if(l==r)break; int mid=(l+r)/2,f=(x>mid); if(!sn[p].son[f])sn[p].son[f]=newnode(); p=sn[p].son[f]; if(x<=mid)r=mid; else l=mid+1; } } int tree[maxN+100]; #define lowbit(a) (a&(-a)) inline void change(int a,int x,int val) { for(;a<=g;a+=lowbit(a)) update(tree[a],1,cnt,x,val); } int r1,r2,r3,r4; int t1[maxN+100],t2[maxN+100],t3[maxN+100],t4[maxN+100]; inline int ask(int p1,int p2,int p3,int p4,int k) { int i,l=1,r=cnt; r1=0;for(;p1>=1;p1-=lowbit(p1))t1[++r1]=tree[p1]; r2=0;for(;p2>=1;p2-=lowbit(p2))t2[++r2]=tree[p2]; r3=0;for(;p3>=1;p3-=lowbit(p3))t3[++r3]=tree[p3]; r4=0;for(;p4>=1;p4-=lowbit(p4))t4[++r4]=tree[p4]; while(l<=r) { if(l==r)return bak[l]; int mid=(l+r)/2,as=0; re(i,1,r1)as+=sn[sn[t1[i]].son[1]].val; re(i,1,r2)as+=sn[sn[t2[i]].son[1]].val; re(i,1,r3)as-=sn[sn[t3[i]].son[1]].val; re(i,1,r4)as-=sn[sn[t4[i]].son[1]].val; if(k<=as) { l=mid+1; re(i,1,r1)t1[i]=sn[t1[i]].son[1]; re(i,1,r2)t2[i]=sn[t2[i]].son[1]; re(i,1,r3)t3[i]=sn[t3[i]].son[1]; re(i,1,r4)t4[i]=sn[t4[i]].son[1]; } else { k-=as; r=mid; re(i,1,r1)t1[i]=sn[t1[i]].son[0]; re(i,1,r2)t2[i]=sn[t2[i]].son[0]; re(i,1,r3)t3[i]=sn[t3[i]].son[0]; re(i,1,r4)t4[i]=sn[t4[i]].son[0]; } } } inline void swim(int &x,int H){int i;for(i=0;H!=0;H>>=1,i++)if(H&1)x=jump[i][x];} inline int ask_lca(int x,int y) { if(dep[x]<dep[y])swap(x,y); swim(x,dep[x]-dep[y]); if(x==y)return x; int i; red(i,30,0)if(jump[i][x]!=jump[i][y]){x=jump[i][x];y=jump[i][y];} return jump[0][x]; } int main() { freopen("bzoj1146.in","r",stdin); freopen("bzoj1146.out","w",stdout); int i; N=gint();Q=gint(); re(i,1,N)T[i]=gint(); mmst(first,-1);now=-1; re(i,1,N-1){int x=gint(),y=gint();addedge(x,y);addedge(y,x);} re(i,1,Q)data[i].input(); re(i,1,N)bak[++cnt]=T[i]; re(i,1,Q)if(data[i].k==0)bak[++cnt]=data[i].b; sort(bak+1,bak+cnt+1); cnt=unique(bak+1,bak+cnt+1)-bak-1; re(i,1,N)T[i]=lower_bound(bak+1,bak+cnt+1,T[i])-bak; re(i,1,Q)if(data[i].k==0)data[i].b=lower_bound(bak+1,bak+cnt+1,data[i].b)-bak; DFS(); re(i,1,g)tree[i]=newnode(); re(i,1,N) { change(l[i],T[i],1); change(r[i]+1,T[i],-1); } re(i,1,Q) { int a=data[i].a,b=data[i].b,k=data[i].k; if(k==0) { change(l[a],T[a],-1);change(r[a]+1,T[a],1); T[a]=b; change(l[a],T[a],1);change(r[a]+1,T[a],-1); } else { int lca=ask_lca(a,b); if(dep[a]+dep[b]-2*dep[lca]+1<k){printf("invalid request! ");continue;} printf("%d ",ask(idx[a],idx[b],idx[lca],idx[fa[lca]],k)); } } return 0; }