Luogu P4175 [CTSC2008]网络管理
dfs序上的带修主席树;求链上的信息仍然是四个点差分,只不过求前缀和变成了 \(\log\) 的树状数组;
#include<cstdio>
#include<iostream>
#include<algorithm>
#define R register int
using namespace std;
namespace Luitaryi {
char B[1<<15],*S=B,*T=B;
#define getchar() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=80010,D=125;
int n,q,c[N],b[N<<1];
int vr[N<<1],nxt[N<<1],fir[N],cnt;
int dfn[N],low[N],son[N],d[N],pre[N],sz[N],top[N],tim;
int ls[N*D],rs[N*D],sum[N*D],rt[N],L;
struct node {int op,u,v;}a[N];
inline void add(int u,int v) {
vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;
vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt;
}
inline void dfs(int u) {
dfn[u]=++tim; sz[u]=1;
for(R i=fir[u];i;i=nxt[i]) {
R v=vr[i];
if(d[v]) continue;
d[v]=d[u]+1,pre[v]=u;
dfs(v);
if(sz[son[u]]<sz[v]) son[u]=v;
} low[u]=tim;
}
inline void dfs2(int u,int tp) {
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(R i=fir[u];i;i=nxt[i]) {
R v=vr[i];
if(v!=son[u]&&v!=pre[u]) dfs2(v,v);
}
}
inline int lca(int u,int v) {
while(top[u]!=top[v]) {
if(d[top[u]]<d[top[v]]) swap(u,v);
u=pre[top[u]];
} return d[u]<d[v]?u:v;
}
inline void change(int& tr,int l,int r,int p,int d) {
if(!tr) tr=++cnt; sum[tr]+=d;
if(l==r) return ; R md=(l+r)>>1;
p<=md?change(ls[tr],l,md,p,d):change(rs[tr],md+1,r,p,d);
}
int m0[31],m1[31];
inline int query(int l,int r,int k) {
if(l==r) return l;
R md=(l+r)>>1,tmp=0;
for(R i=1;i<=m0[0];++i) tmp+=sum[ls[m0[i]]];
for(R i=1;i<=m1[0];++i) tmp-=sum[ls[m1[i]]];
if(k<=tmp) {
for(R i=1;i<=m0[0];++i) m0[i]=ls[m0[i]];
for(R i=1;i<=m1[0];++i) m1[i]=ls[m1[i]];
return query(l,md,k);
} else {
for(R i=1;i<=m0[0];++i) m0[i]=rs[m0[i]];
for(R i=1;i<=m1[0];++i) m1[i]=rs[m1[i]];
return query(md+1,r,k-tmp);
}
}
inline void change(int x,int v,int op) {
for(;x<=n;x+=x&-x) change(rt[x],1,L,v,op);
}
inline void main() {
n=g(),q=g();
for(R i=1;i<=n;++i) b[i]=c[i]=g();
for(R i=1,u,v;i<n;++i)
u=g(),v=g(),add(u,v);
d[1]=1; dfs(1),dfs2(1,1),L=n;
for(R i=1;i<=q;++i) {
a[i].op=g(),a[i].u=g(),a[i].v=g();
if(!a[i].op) b[++L]=a[i].v;
}
sort(b+1,b+L+1),L=unique(b+1,b+L+1)-b-1;
for(R i=1;i<=n;++i) c[i]=lower_bound(b+1,b+L+1,c[i])-b;
for(R i=1;i<=n;++i) change(dfn[i],c[i],1),change(low[i]+1,c[i],-1);
for(R i=1,op,u,v,l,fl,tmp;i<=q;++i) {
op=a[i].op,u=a[i].u,v=a[i].v;
if(op) {
l=lca(u,v),fl=pre[l];
tmp=d[u]+d[v]-d[l]-d[fl];
if(op>tmp) {puts("invalid request!"); continue;}
m0[0]=m1[0]=0;
for(R i=dfn[u];i;i-=i&-i) m0[++m0[0]]=rt[i];
for(R i=dfn[v];i;i-=i&-i) m0[++m0[0]]=rt[i];
for(R i=dfn[l];i;i-=i&-i) m1[++m1[0]]=rt[i];
for(R i=dfn[fl];i;i-=i&-i) m1[++m1[0]]=rt[i];
printf("%d\n",b[query(1,L,tmp-op+1)]);
} else {
change(dfn[u],c[u],-1),change(low[u]+1,c[u],1);
c[u]=lower_bound(b+1,b+L+1,v)-b;
change(dfn[u],c[u],1),change(low[u]+1,c[u],-1);
}
}
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.20