【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.

 

posted on 2017-01-02 18:47  myx12345  阅读(192)  评论(0编辑  收藏  举报

导航