【BZOJ3123】森林(主席树,启发式合并)
题意:一个带点权的森林,要求维护以下操作:
1.询问路径上的点权K大值
2.两点之间连边
n,m<=80000
思路:如果树的结构不发生变化只需要维护DFS序
现在因为树的结构发生变化,要将两棵树合并,这步可以用启发式合并,将比较小的树暴力连接到较大的树上面
离线的LCA算法无法维护,而倍增可以合并,所以用倍增求LCA
其余就是主席树,维护根到点的权值线段树就行了
机房里的罗爷爷写法比我高到不知道哪里去了
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 const int M=200010; 6 int cas,n,m,q,i,x,y,k,edgenum,cnt,ans; 7 int a[M],b[M],c[M],head[M],vet[M],next[M],dep[M],fa[M][20],f[M],size[M],root[M]; 8 struct node{int l,r,w;}tree[M*100]; 9 bool cmp(int x,int y){return a[x]<a[y];} 10 int search(int x){ 11 if (f[x]!=x)f[x]=search(f[x]); 12 return f[x]; 13 } 14 void addedge(int x,int y){ 15 vet[++edgenum]=y; 16 next[edgenum]=head[x]; 17 head[x]=edgenum; 18 } 19 void update(int x,int l,int r,int &p){ 20 tree[++cnt]=tree[p];p=cnt;tree[p].w++; 21 if (l==r)return; 22 int mid=l+r>>1; 23 if (x<=mid)update(x,l,mid,tree[p].l); 24 else update(x,mid+1,r,tree[p].r); 25 } 26 int query(int l,int r,int k,int x,int y,int z,int w){ 27 if (l==r)return l; 28 int mid=l+r>>1,t=tree[tree[x].l].w+tree[tree[y].l].w-tree[tree[z].l].w-tree[tree[w].l].w; 29 if (t>=k)return query(l,mid,k,tree[x].l,tree[y].l,tree[z].l,tree[w].l); 30 else return query(mid+1,r,k-t,tree[x].r,tree[y].r,tree[z].r,tree[w].r); 31 } 32 int lca(int x,int y){ 33 if (dep[x]<dep[y])swap(x,y); 34 int t=dep[x]-dep[y]; 35 for (int i=0;i<=16;i++) 36 if (t&(1<<i))x=fa[x][i]; 37 for (int i=16;i>=0;i--) 38 if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; 39 if (x==y)return x; 40 return fa[x][0]; 41 } 42 void dfs(int u,int pre){ 43 fa[u][0]=pre; 44 for (int i=1;i<=16;i++)fa[u][i]=fa[fa[u][i-1]][i-1]; 45 root[u]=root[pre]; 46 update(c[u],1,n,root[u]); 47 for (int e=head[u];e;e=next[e]){ 48 int v=vet[e]; 49 if (v==pre)continue; 50 dep[v]=dep[u]+1; 51 dfs(v,u); 52 } 53 } 54 void link(int x,int y){ 55 int p=search(x),q=search(y); 56 if (size[p]>size[q]){swap(x,y);swap(p,q);} 57 dep[x]=dep[y]+1; 58 dfs(x,y); 59 f[p]=q;size[q]+=size[p]; 60 addedge(x,y); 61 addedge(y,x); 62 } 63 int main(){ 64 scanf("%d",&cas); 65 scanf("%d%d%d",&n,&m,&q); 66 for (i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=i; 67 sort(b+1,b+n+1,cmp); 68 for (i=1;i<=n;i++)c[b[i]]=i; 69 for (i=1;i<=n;i++)f[i]=i,size[i]=1; 70 cnt=n; 71 for (i=1;i<=n;i++)root[i]=i,update(c[i],1,n,root[i]); 72 for (i=1;i<=m;i++){ 73 scanf("%d%d",&x,&y); 74 link(x,y); 75 } 76 while (q--){ 77 char s[10]; 78 scanf("%s",s); 79 if (s[0]=='L'){ 80 scanf("%d%d",&x,&y); 81 x^=ans;y^=ans; 82 link(x,y); 83 }else{ 84 scanf("%d%d%d",&x,&y,&k); 85 x^=ans;y^=ans;k^=ans; 86 int z=lca(x,y); 87 printf("%d\n",ans=a[b[query(1,n,k,root[x],root[y],root[z],root[fa[z][0]])]]); 88 } 89 } 90 }
这是我的萎靡写法
1 var t:array[0..22000000]of record 2 l,r,s:longint; 3 end; 4 f:array[0..300000,0..20]of longint; 5 root,head,c,a,hash,h,dep,stk,size:array[0..500000]of longint; 6 vet,next:array[0..610000]of longint; 7 n,m,x,y,z,lastans,i,j,tot,cnt,k,s,up,top,que:longint; 8 ch:string; 9 10 procedure swap(var x,y:longint); 11 var t:longint; 12 begin 13 t:=x; x:=y; y:=t; 14 end; 15 16 procedure qsort(l,r:longint); 17 var i,j,mid:longint; 18 begin 19 i:=l; j:=r; mid:=c[(l+r)>>1]; 20 repeat 21 while mid>c[i] do inc(i); 22 while mid<c[j] do dec(j); 23 if i<=j then 24 begin 25 swap(c[i],c[j]); 26 inc(i); dec(j); 27 end; 28 until i>j; 29 if l<j then qsort(l,j); 30 if i<r then qsort(i,r); 31 end; 32 33 function lsh(x:longint):longint; 34 var l,r,mid:longint; 35 begin 36 l:=1; r:=up; 37 while l<=r do 38 begin 39 mid:=(l+r)>>1; 40 if x=hash[mid] then exit(mid); 41 if x<hash[mid] then r:=mid-1 42 else l:=mid+1; 43 end; 44 end; 45 46 function find(k:longint):longint; 47 begin 48 if h[k]<>k then h[k]:=find(h[k]); 49 exit(h[k]); 50 end; 51 52 procedure add(a,b:longint); 53 begin 54 inc(tot); 55 next[tot]:=head[a]; 56 vet[tot]:=b; 57 head[a]:=tot; 58 end; 59 60 procedure pushup(p:longint); 61 begin 62 t[p].s:=t[t[p].l].s+t[t[p].r].s; 63 end; 64 65 procedure update(l,r,x:longint;var y:longint;v:longint); 66 var mid:longint; 67 begin 68 inc(cnt); y:=cnt; 69 t[y]:=t[x]; inc(t[y].s); 70 if l=r then exit; 71 mid:=(l+r)>>1; 72 if v<=mid then update(l,mid,t[x].l,t[y].l,v) 73 else update(mid+1,r,t[x].r,t[y].r,v); 74 pushup(y); 75 end; 76 77 procedure dfs(u,pre:longint); 78 var e,v,x,y:longint; 79 begin 80 update(1,up,root[pre],root[u],a[u]); 81 e:=head[u]; 82 dep[u]:=dep[pre]+1; 83 f[u,0]:=pre; 84 while e<>0 do 85 begin 86 v:=vet[e]; 87 if v<>pre then 88 begin 89 dfs(v,u); 90 x:=find(v); y:=find(u); 91 if size[x]<size[y] then 92 begin 93 size[x]:=size[y]+size[x]; 94 h[y]:=x; 95 end 96 else begin size[y]:=size[x]+size[y]; h[x]:=y; end; 97 end; 98 e:=next[e]; 99 end; 100 end; 101 102 function lca(x,y:longint):longint; 103 var i,d:longint; 104 begin 105 if dep[x]<dep[y] then swap(x,y); 106 d:=dep[x]-dep[y]; 107 for i:=0 to 20 do 108 if d and (1<<i)>0 then x:=f[x,i]; 109 for i:=20 downto 0 do 110 if f[x,i]<>f[y,i] then 111 begin 112 x:=f[x,i]; y:=f[y,i]; 113 end; 114 if x=y then exit(x); 115 exit(f[x,0]); 116 end; 117 118 function query(l,r,x,y,z,w,k:longint):longint; 119 var mid,tmp:longint; 120 begin 121 if l=r then exit(l); 122 mid:=(l+r)>>1; 123 tmp:=t[t[x].l].s+t[t[y].l].s-t[t[z].l].s-t[t[w].l].s; 124 if tmp>=k then 125 begin 126 x:=t[x].l; y:=t[y].l; z:=t[z].l; w:=t[w].l; 127 exit(query(l,mid,x,y,z,w,k)); 128 end 129 else 130 begin 131 x:=t[x].r; y:=t[y].r; z:=t[z].r; w:=t[w].r; 132 exit(query(mid+1,r,x,y,z,w,k-tmp)); 133 end; 134 end; 135 136 function ask(x,y,z:longint):longint; 137 var q:longint; 138 begin 139 q:=lca(x,y); 140 exit(hash[query(1,up,root[x],root[y],root[q],root[f[q,0]],z)]); 141 end; 142 143 procedure rebuild(u,pre:longint); 144 var e,v:longint; 145 begin 146 inc(top); stk[top]:=u; 147 update(1,up,root[pre],root[u],a[u]); 148 dep[u]:=dep[pre]+1; 149 f[u,0]:=pre; 150 e:=head[u]; 151 while e<>0 do 152 begin 153 v:=vet[e]; 154 if v<>pre then rebuild(v,u); 155 e:=next[e]; 156 end; 157 end; 158 159 procedure merge(x,y:longint); 160 var tx,ty,z,i,j:longint; 161 begin 162 tx:=find(x); ty:=find(y); 163 if size[tx]>size[ty] then 164 begin 165 swap(tx,ty); swap(x,y); 166 end; 167 top:=0; 168 add(x,y); add(y,x); 169 rebuild(x,y); 170 h[tx]:=ty; size[ty]:=size[ty]+size[tx]; 171 for i:=1 to 20 do 172 for j:=1 to top do 173 begin 174 z:=stk[j]; 175 f[z,i]:=f[f[z,i-1],i-1]; 176 end; 177 end; 178 179 begin 180 assign(input,'bzoj3123.in'); reset(input); 181 assign(output,'bzoj3123.out'); rewrite(output); 182 readln(x); 183 readln(n,m,que); 184 for i:=1 to n do 185 begin 186 read(a[i]); 187 c[i]:=a[i]; 188 end; 189 qsort(1,n); 190 up:=1; hash[1]:=c[1]; 191 for i:=2 to n do 192 if c[i]<>c[i-1] then begin inc(up); hash[up]:=c[i]; end; 193 for i:=1 to n do a[i]:=lsh(a[i]); 194 for i:=1 to m do 195 begin 196 readln(x,y); 197 add(x,y); 198 add(y,x); 199 end; 200 for i:=1 to n do 201 begin 202 h[i]:=i; size[i]:=1; 203 end; 204 for i:=1 to n do 205 if root[i]=0 then dfs(i,0); 206 for i:=1 to 20 do 207 for j:=1 to n do f[j,i]:=f[f[j,i-1],i-1]; 208 for i:=1 to que do 209 begin 210 readln(ch); s:=0; k:=length(ch); x:=0; y:=0; z:=0; 211 for j:=2 to k do 212 begin 213 if ch[j]=' ' then begin if ch[j-1]<>' ' then inc(s); continue; end; 214 if s=1 then x:=x*10+ord(ch[j])-ord('0'); 215 if s=2 then y:=y*10+ord(ch[j])-ord('0'); 216 if s=3 then z:=z*10+ord(ch[j])-ord('0'); 217 end; 218 if ch[1]='Q' then 219 begin 220 x:=x xor lastans; y:=y xor lastans; z:=z xor lastans; //writeln(x,' ',y,' ',z); 221 k:=ask(x,y,z); 222 writeln(k); 223 lastans:=k; 224 end 225 else 226 begin 227 x:=x xor lastans; y:=y xor lastans;// writeln(x,' ',y,' ',z); 228 merge(x,y); 229 end; 230 231 end; 232 close(input); 233 close(output); 234 end.
null