bzoj3572: [Hnoi2014]世界树

3572: [Hnoi2014]世界树

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1325  Solved: 732
[Submit][Status][Discuss]

Description

世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界。在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息、持续运转的根本基石。
世界树的形态可以用一个数学模型来描述:世界树中有n个种族,种族的编号分别从1到n,分别生活在编号为1到n的聚居地上,种族的编号与其聚居地的编号相同。有的聚居地之间有双向的道路相连,道路的长度为1。保证连接的方式会形成一棵树结构,即所有的聚居地之间可以互相到达,并且不会出现环。定义两个聚居地之间的距离为连接他们的道路的长度;例如,若聚居地a和b之间有道路,b和c之间有道路,因为每条道路长度为1而且又不可能出现环,所卧a与c之间的距离为2。
出于对公平的考虑,第i年,世界树的国王需要授权m[i]个种族的聚居地为临时议事处。对于某个种族x(x为种族的编号),如果距离该种族最近的临时议事处为y(y为议事处所在聚居地的编号),则种族x将接受y议事处的管辖(如果有多个临时议事处到该聚居地的距离一样,则y为其中编号最小的临时议事处)。
现在国王想知道,在q年的时间里,每一年完成授权后,当年每个临时议事处将会管理多少个种族(议事处所在的聚居地也将接受该议事处管理)。 现在这个任务交给了以智慧著称的灵长类的你:程序猿。请帮国王完成这个任务吧。

Input

第一行为一个正整数n,表示世界树中种族的个数。
接下来n-l行,每行两个正整数x,y,表示x聚居地与y聚居地之间有一条长度为1的双
向道路。接下来一行为一个正整数q,表示国王询问的年数。
接下来q块,每块两行:
第i块的第一行为1个正整数m[i],表示第i年授权的临时议事处的个数。
第i块的第二行为m[i]个正整数h[l]、h[2]、…、h[m[i]],表示被授权为临时议事处的聚居地编号(保证互不相同)。

Output

输出包含q行,第i行为m[i]个整数,该行的第j(j=1,2…,,m[i])个数表示第i年被授权的聚居地h[j]的临时议事处管理的种族个数。

Sample Input

10
2 1
3 2
4 3
5 4
6 1
7 3
8 3
9 4
10 1
5
2
6 1
5
2 7 3 6 9
1
8
4
8 7 10 3
5
2 9 3 5 8

Sample Output

1 9
3 1 4 1 1
10
1 1 3 5
4 1 3 1 1

HINT

 

N<=300000, q<=300000,m[1]+m[2]+…+m[q]<=300000

 
题解
建立虚树,因为虚树上的点并不都是给出的点,所以要从下向上再从上向下扫两遍,求出数组bel,即距离虚树上每个点最近的给出的点。然后对于每一条虚边上的点,控制它的一定是两端点的bel,二分(其实是在倍增出的祖先数组中跳)出分界点,然后算一下。具体细节看代码吧,感觉还是又不少要注意的地方
//因为扫的顺序搞错了吃了好几发WA
  1 program j01;
  2 const maxn=300086;
  3 var f:array[0..maxn,0..20]of longint;
  4     fa,dfn,h,head,bin,id,ans,dep:array[0..maxn]of longint;
  5     q,next:array[0..2*maxn]of longint;
  6     st,cnt,bel,rem,size,tmp,del:array[0..maxn]of longint;
  7     vis:array[0..maxn]of boolean;
  8     n,m,u,v,i,tt,time:longint;
  9 
 10 procedure add(u,v:longint);
 11 begin
 12   inc(tt);q[tt]:=v;next[tt]:=head[u];head[u]:=tt;
 13 end;
 14 
 15 procedure swap(var a,b:longint);
 16 var c:longint;
 17 begin
 18   c:=a;a:=b;b:=c;
 19 end;
 20 
 21 procedure dfs(i:longint);
 22 var j:longint;
 23 begin
 24   for j:=1 to bin[dep[i]] do
 25     f[i,j]:=f[f[i,j-1],j-1];
 26   size[i]:=1;inc(time);dfn[i]:=time;
 27   j:=head[i];
 28   while j>0 do
 29   begin
 30     if q[j]<>f[i,0] then
 31     begin
 32       dep[q[j]]:=dep[i]+1;
 33       f[q[j],0]:=i;
 34       dfs(q[j]);
 35       inc(size[i],size[q[j]]);
 36     end;
 37     j:=next[j];
 38   end;
 39 end;
 40 
 41 function cmp(a,b:longint):boolean;
 42 begin
 43   exit(dfn[a]<dfn[b]);
 44 end;
 45 
 46 procedure sort(l,r:longint);
 47 var i,j,x:longint;
 48 begin
 49   i:=l;j:=r;x:=h[(i+j)div 2];
 50   repeat
 51     while cmp(h[i],x) do inc(i);
 52     while cmp(x,h[j]) do dec(j);
 53     if i<=j then
 54     begin
 55       swap(h[i],h[j]);swap(id[i],id[j]);
 56       inc(i);dec(j);
 57     end;
 58   until i>j;
 59   if i<r then sort(i,r);
 60   if l<j then sort(l,j);
 61 end;
 62 
 63 function lca(u,v:longint):longint;
 64 var d,i:longint;
 65 begin
 66   if u=v then exit(u);
 67   if dep[u]<dep[v] then swap(u,v);
 68   d:=dep[u]-dep[v];
 69   for i:=bin[d] downto 0 do
 70     if d and(1 shl i)>0 then u:=f[u,i];
 71   for i:=bin[dep[u]] downto 0 do
 72     if f[u,i]<>f[v,i] then
 73     begin
 74       u:=f[u,i];v:=f[v,i];
 75     end;
 76   if u=v then exit(u) else exit(f[u,0]);
 77 end;
 78 
 79 procedure ins(u,v:longint);
 80 begin
 81   fa[v]:=u;
 82 end;
 83 
 84 procedure qsort(l,r:longint);
 85 var i,j,x:longint;
 86 begin
 87   i:=l;j:=r;x:=tmp[(i+j)div 2];
 88   repeat
 89     while cmp(tmp[i],x) do inc(i);
 90     while cmp(x,tmp[j]) do dec(j);
 91     if i<=j then
 92     begin
 93       swap(tmp[i],tmp[j]);
 94       inc(i);dec(j);
 95     end;
 96   until i>j;
 97   if i<r then qsort(i,r);
 98   if l<j then qsort(l,j);
 99 end;
100 
101 function dis(u,v:longint):longint;
102 begin
103   exit(dep[u]+dep[v]-2*dep[lca(u,v)]);
104 end;
105 
106 
107 procedure sol(u,v:longint);
108 var i,t1,t2,x,mid,nxt:longint;
109 begin
110   x:=v;
111   for i:=bin[dep[v]] downto 0 do
112     if dep[f[x,i]]>dep[u] then x:=f[x,i];
113   dec(rem[u],size[x]);
114   if bel[u]=bel[v] then
115   begin
116     inc(cnt[bel[u]],size[x]-size[v]);
117     exit;
118   end;
119   mid:=v;
120   for i:=bin[dep[v]] downto 0 do
121   begin
122     nxt:=f[mid,i];
123     if dep[nxt]<=dep[u] then continue;
124     t1:=dis(bel[u],nxt);t2:=dis(bel[v],nxt);
125     if(t1>t2)or((t1=t2)and(bel[u]>bel[v])) then mid:=nxt;
126   end;
127   inc(cnt[bel[u]],size[x]-size[mid]);
128   inc(cnt[bel[v]],size[mid]-size[v]);
129 end;
130 
131 procedure solve;
132 var i,j,ff,top,x,k,tot,t1,t2:longint;
133 begin
134   readln(k);
135   for i:=1 to k do
136   begin
137     read(h[i]);vis[h[i]]:=true;cnt[h[i]]:=0;id[i]:=i;
138   end;
139   sort(1,k);
140   st[1]:=1;top:=1;tmp[1]:=1;tot:=1;
141   if vis[1] then bel[1]:=1 else bel[1]:=0;
142   for i:=1 to k do
143   begin
144     if h[i]=st[top] then continue;
145     x:=h[i];ff:=lca(x,st[top]);
146     while(top>1)and(dep[ff]<dep[st[top-1]]) do
147     begin
148       ins(st[top-1],st[top]);dec(top);
149     end;
150     if st[top]<>ff then ins(ff,st[top]);
151     if st[top-1]<>ff then
152     begin
153       if tmp[tot]<>ff then
154       begin
155         inc(tot);tmp[tot]:=ff;
156       end;
157       st[top]:=ff;
158       if vis[ff] then bel[ff]:=ff else bel[ff]:=0;
159     end else dec(top);
160     inc(top);st[top]:=x;inc(tot);tmp[tot]:=x;
161     if vis[x] then bel[x]:=x else bel[x]:=0;
162   end;
163   while top>1 do
164   begin
165     ins(st[top-1],st[top]);dec(top);
166   end;
167   qsort(1,tot);
168   for j:=tot downto 2 do
169   begin
170     i:=tmp[j];
171     t1:=dis(fa[i],bel[i]);t2:=dis(fa[i],bel[fa[i]]);
172     if(t1<t2)or((t1=t2)and(bel[i]<bel[fa[i]]))or(bel[fa[i]]=0) then
173       bel[fa[i]]:=bel[i];
174   end;
175   for j:=1 to tot do
176   begin
177     i:=tmp[j];
178     rem[i]:=size[i];if i=1 then continue;
179     t1:=dis(i,bel[i]);t2:=dis(i,bel[fa[i]]);
180     if(t1>t2)or((t1=t2)and(bel[fa[i]]<bel[i]))or(bel[i]=0) then
181       bel[i]:=bel[fa[i]];
182   end;
183   for i:=2 to tot do
184     sol(fa[tmp[i]],tmp[i]);
185   for i:=1 to tot do inc(cnt[bel[tmp[i]]],rem[tmp[i]]);
186   for i:=1 to k do ans[id[i]]:=cnt[h[i]];
187   for i:=1 to k do vis[h[i]]:=false;
188   for i:=1 to k do write(ans[i],' ');writeln;
189 end;
190 
191 begin
192   //assign(input,'1.in');reset(input);
193   readln(n);
194   fillchar(head,sizeof(head),0);
195   for i:=1 to n-1 do
196   begin
197     readln(u,v);add(u,v);add(v,u);
198   end;
199   bin[1]:=0;
200   for i:=2 to n do
201     if i and(i-1)=0 then bin[i]:=bin[i-1]+1 else bin[i]:=bin[i-1];
202   dep[1]:=0;time:=0;
203   dfs(1);
204   readln(m);
205   for i:=1 to m do
206   begin
207     solve;
208   end;
209 end.
View Code

 

posted @ 2017-02-13 10:53  OldJang  阅读(129)  评论(0编辑  收藏  举报