[BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值。
思路:
1.DFS序+树状数组套主席树
首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息。
关于询问,就是Que(u)+Que(v)-Que(LCA(u,v))-Que(father(LCA(u,v))),线段树上二分查询第k大即可。
考虑修改,修改一个点影响到的点为它子树中的所有点,所以要用DFS序。于是这实际上是区间修改单点询问的问题,外面套一层主席树即可。
$O(n\log^2 n)$
2.二分+树链剖分+线段树套平衡树
由于是链上询问,考虑树链剖分。首先二分答案mid,然后问题转化为求mid在这条链上的排名,在树链上用线段树维护,每棵树中维护一棵平衡树,用来求排名。
$O(n\log^4 n)$理论上会超但实际上常数比较小。
第一种码力太弱码不出来,写了第二种,速度OJ上倒数(空间倒是十分优秀)。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ls (x<<1) 5 #define rs (ls|1) 6 #define lson ls,L,mid 7 #define rson rs,mid+1,R 8 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 9 #define For(i,x) for (int i=h[x],k; i; i=nxt[i]) 10 using namespace std; 11 12 const int N=100010,M=2000010; 13 bool vis[N]; 14 int n,Q,cnt,tot,nd,tmp,tim,ans,u,v; 15 int val[M],lc[M],rc[M],hp[M],sz[M],w[M]; 16 int T[N],pos[N],b[N<<1],fa[N],son[N],dep[N],top[N],root[N<<2]; 17 int h[N],to[N<<1],nxt[N<<1]; 18 struct Que{ int k,a,b; }q[N]; 19 20 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 21 22 void dfs1(int x){ 23 sz[x]=1; 24 For(i,x) if ((k=to[i])!=fa[x]){ 25 fa[k]=x; dep[k]=dep[x]+1; dfs1(k); sz[x]+=sz[k]; 26 if (sz[k]>sz[son[x]]) son[x]=k; 27 } 28 } 29 30 void dfs2(int x,int tp){ 31 top[x]=tp; pos[x]=++tim; 32 if (son[x]) dfs2(son[x],tp); 33 For(i,x) if ((k=to[i])!=fa[x] && k!=son[x]) dfs2(k,k); 34 } 35 36 int lca(int u,int v){ 37 for (; top[u]!=top[v]; u=fa[top[u]]) 38 if (dep[top[u]]<dep[top[v]]) swap(u,v); 39 return (dep[u]<dep[v]) ? u : v; 40 } 41 42 void rrot(int &x){ 43 int y=lc[x]; lc[x]=rc[y]; rc[y]=x; 44 sz[y]=sz[x]; sz[x]=sz[lc[x]]+sz[rc[x]]+w[x]; x=y; 45 } 46 47 void lrot(int &x){ 48 int y=rc[x]; rc[x]=lc[y]; lc[y]=x; 49 sz[y]=sz[x]; sz[x]=sz[lc[x]]+sz[rc[x]]+w[x]; x=y; 50 } 51 52 void ins(int &x,int k){ 53 if (!x) { x=++nd; sz[x]=w[x]=1; hp[x]=rand(); val[x]=k; return; } 54 sz[x]++; 55 if (k==val[x]) { w[x]++; return; } 56 if (k<val[x]){ ins(lc[x],k); if (hp[lc[x]]<hp[x]) rrot(x); } 57 else{ ins(rc[x],k); if (hp[rc[x]]<hp[x]) lrot(x); } 58 } 59 60 void del(int &x,int k){ 61 if (val[x]==k){ 62 if (w[x]>1) { sz[x]--; w[x]--; return; } 63 if (!lc[x] || !rc[x]) { x=lc[x]+rc[x]; return; } 64 if (hp[lc[x]]<hp[rc[x]]) rrot(x),del(x,k); 65 else lrot(x),del(x,k); 66 return; 67 } 68 sz[x]--; 69 if (k<val[x]) del(lc[x],k); else del(rc[x],k); 70 } 71 72 void getrank(int x,int k){ 73 if (!x) return; 74 if (val[x]==k) tmp+=sz[rc[x]]; 75 else if (k>val[x]) getrank(rc[x],k); else tmp+=sz[rc[x]]+w[x],getrank(lc[x],k); 76 } 77 78 void mdf(int x,int L,int R,int pos,int a,int b){ 79 if (~a) del(root[x],a); ins(root[x],b); 80 if (L==R) return; 81 int mid=(L+R)>>1; 82 if (pos<=mid) mdf(lson,pos,a,b); else mdf(rson,pos,a,b); 83 } 84 85 void que(int x,int L,int R,int l,int r,int k){ 86 if (L==l && r==R){ getrank(root[x],k); return; } 87 int mid=(L+R)>>1; 88 if (r<=mid) que(lson,l,r,k); 89 else if (l>mid) que(rson,l,r,k); 90 else que(lson,l,mid,k),que(rson,mid+1,r,k); 91 } 92 93 void Get(int x,int f,int k){ 94 while (top[x]!=top[f]) que(1,1,n,pos[top[x]],pos[x],k),x=fa[top[x]]; 95 que(1,1,n,pos[f],pos[x],k); 96 } 97 98 void solve(int x,int y,int k){ 99 int t=lca(x,y); ans=-1; 100 if (dep[x]+dep[y]-dep[t]-dep[fa[t]]<k){ puts("invalid request!"); return; } 101 int L=1,R=tot; 102 while (L<=R){ 103 int mid=(L+R)>>1; 104 tmp=0; Get(x,t,mid); Get(y,t,mid); 105 if (T[t]>mid) tmp--; 106 if (tmp<k) R=mid-1,ans=mid; else L=mid+1; 107 } 108 printf("%d\n",b[ans]); 109 } 110 111 int main(){ 112 freopen("bzoj1146.in","r",stdin); 113 freopen("bzoj1146.out","w",stdout); 114 scanf("%d%d",&n,&Q); 115 rep(i,1,n) scanf("%d",&T[i]),b[++tot]=T[i]; 116 rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u); 117 dep[1]=1; dfs1(1); dfs2(1,1); 118 rep(i,1,Q){ 119 scanf("%d%d%d",&q[i].k,&q[i].a,&q[i].b); 120 if (!q[i].k) b[++tot]=q[i].b; 121 } 122 sort(b+1,b+tot+1); tot=unique(b+1,b+tot+1)-b-1; 123 rep(i,1,n) T[i]=lower_bound(b+1,b+tot+1,T[i])-b; 124 rep(i,1,Q) if (!q[i].k) q[i].b=lower_bound(b+1,b+tot+1,q[i].b)-b; 125 rep(i,1,n) mdf(1,1,n,pos[i],-1,T[i]); 126 rep(i,1,Q) 127 if (!q[i].k) mdf(1,1,n,pos[q[i].a],T[q[i].a],q[i].b),T[q[i].a]=q[i].b; 128 else solve(q[i].a,q[i].b,q[i].k); 129 return 0; 130 }