BZOJ1095: [ZJOI2007]Hide 捉迷藏(动态点分治)

Description

  捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
距离。

Input

  第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
上文所示。

Output

  对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
着灯的,输出0;若所有房间的灯都开着,输出-1。

Sample Input

8
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G

Sample Output

4
3
3
4

解题思路:

可以将开灯的点都压缩一下,那么这道题就变成了动态求一颗树的直径。

静态的直径可以由一个点子树中不重复的最大值和次大值来更新。

那么可以考虑更新一个点后重新实现Dfs回溯过程,这时候,我们就需要用一个堆来记录这个点的最长链。

那样问题就变成了枚举两个儿子更新答案。

实际上这是不需要的,在每个点再开一个堆记录答案就好了。

最后将每个点的答案记录到的答案推入答案堆中。

这个复杂度还是不能承受。

将树重构形成点分树,每次都在树中暴力更新答案(注意距离要重新到原树中计算)。

代码:(不想写带删除优先队列,就写了个Treap好慢啊QAQ)

  1 #include<ctime>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 typedef long long lnt;
  6 const int N=100010;
  7 struct pnt{
  8     int f;
  9     int fa;
 10     int hd;
 11     int dp;
 12     int tp;
 13     int dis;
 14     int wgt;
 15     int val;
 16     int mxs;
 17     int dcrt;
 18     int cnrt;
 19     bool vis;
 20 }p[N];
 21 struct trnt{
 22     int ls;
 23     int rs;
 24     int val;
 25     int num;
 26     int wgt;
 27     int rnd;
 28 }tr[N*80],strn;
 29 struct ent{
 30     int twd;
 31     int lst;
 32 }e[N<<1];
 33 int n,m;
 34 int cnt;
 35 int dfn;
 36 int siz;
 37 int top;
 38 int del;
 39 int bnum;
 40 int root;
 41 int size;
 42 int maxsize;
 43 int ansroot;
 44 int sta[N];
 45 int bin[N*80];
 46 char cmd[1000];
 47 void pushup(int rt)
 48 {
 49     if(!rt)
 50         return ;
 51     tr[rt].wgt=tr[tr[rt].ls].wgt+tr[tr[rt].rs].wgt+tr[rt].num;
 52     return ;
 53 }
 54 void lturn(int &rt)
 55 {
 56     int ll=tr[rt].ls;
 57     tr[rt].ls=tr[ll].rs;
 58     tr[ll].rs=rt;
 59     pushup(rt);
 60     rt=ll;
 61     pushup(rt);
 62     return ;
 63 }
 64 void rturn(int &rt)
 65 {
 66     int rr=tr[rt].rs;
 67     tr[rt].rs=tr[rr].ls;
 68     tr[rr].ls=rt;
 69     pushup(rt);
 70     rt=rr;
 71     pushup(rt);
 72     return ;
 73 }
 74 int newp(void)
 75 {
 76     if(bnum)
 77         return bin[bnum--];
 78     return ++siz;
 79 }
 80 void apply(int &rt)
 81 {
 82     rt=newp();
 83     tr[rt]=strn;
 84     tr[rt].num=1;
 85     tr[rt].rnd=rand();
 86     return ;
 87 }
 88 void Del(int rt)
 89 {
 90     bin[++bnum]=rt;
 91     return ;
 92 }
 93 void Insert(int &rt,int v)
 94 {
 95     if(!rt)
 96     {
 97         apply(rt);
 98         tr[rt].val=v;
 99         pushup(rt);
100         return ;
101     }
102     if(tr[rt].val==v)
103         tr[rt].num++;
104     else if(tr[rt].val>v)
105     {
106         Insert(tr[rt].ls,v);
107         if(tr[rt].rnd>tr[tr[rt].ls].rnd)
108             lturn(rt);
109     }else{
110         Insert(tr[rt].rs,v);
111         if(tr[rt].rnd>tr[tr[rt].rs].rnd)
112             rturn(rt);
113     }
114     pushup(rt);
115     return ;
116 }
117 void Delete(int &rt,int v)
118 {
119     if(!rt)
120         return ;
121     if(tr[rt].val==v)
122     {
123         if(tr[rt].num<=1)
124         {
125             if(!tr[rt].ls||!tr[rt].rs)
126             {
127                 Del(rt);
128                 rt=tr[rt].ls+tr[rt].rs;
129                 return ;
130             }else{
131                 if(tr[tr[rt].ls].rnd<tr[tr[rt].rs].rnd)
132                 {
133                     lturn(rt);
134                     Delete(tr[rt].rs,v);
135                 }else{
136                     rturn(rt);
137                     Delete(tr[rt].ls,v);
138                 }
139             }
140         }else
141             tr[rt].num--;
142     }else if(tr[rt].val>v)
143         Delete(tr[rt].ls,v);
144     else
145         Delete(tr[rt].rs,v);
146     pushup(rt);
147     return ;
148 }
149 int kth(int rt,int k)
150 {
151     if(tr[tr[rt].ls].wgt>=k)
152         return kth(tr[rt].ls,k);
153     if(tr[tr[rt].ls].wgt+tr[rt].num>=k)
154         return tr[rt].val;
155     return kth(tr[rt].rs,k-tr[tr[rt].ls].wgt-tr[rt].num);
156 }
157 int Maxval(int rt)
158 {
159     if(tr[rt].wgt==0)
160         return -0x3f3f3f3f;
161     return kth(rt,tr[rt].wgt);
162 }
163 int Secval(int rt)
164 {
165     if(tr[rt].wgt<=1)
166         return -0x3f3f3f3f;
167     return kth(rt,tr[rt].wgt-1);
168 }
169 int Chain(int rt)
170 {
171     if(tr[rt].wgt<2)
172         return 0;
173     return std::max(0,Maxval(rt)+Secval(rt));
174 }
175 void ade(int f,int t)
176 {
177     cnt++;
178     e[cnt].twd=t;
179     e[cnt].lst=p[f].hd;
180     p[f].hd=cnt;
181     return ;
182 }
183 void Basic_dfs(int x,int f)
184 {
185     p[x].wgt=1;
186     p[x].f=f;
187     p[x].dp=p[f].dp+1;
188     int maxs=-1;
189     for(int i=p[x].hd;i;i=e[i].lst)
190     {
191         int to=e[i].twd;
192         if(to==f)
193             continue;
194         p[to].dis=p[x].dis+1;
195         Basic_dfs(to,x);
196         p[x].wgt+=p[to].wgt;
197         if(maxs<p[to].wgt)
198         {
199             maxs=p[to].wgt;
200             p[x].mxs=to;
201         }
202     }
203     return ;
204 }
205 void Build_dfs(int x,int top)
206 {
207     if(!x)
208         return ;
209     p[x].tp=top;
210     Build_dfs(p[x].mxs,top);
211     for(int i=p[x].hd;i;i=e[i].lst)
212     {
213         int to=e[i].twd;
214         if(to==p[x].f||to==p[x].mxs)
215             continue;
216         Build_dfs(to,to);
217     }
218     return ;
219 }
220 int Lca(int x,int y)
221 {
222     while(p[x].tp!=p[y].tp)
223     {
224         if(p[p[x].tp].dp<p[p[y].tp].dp)
225             std::swap(x,y);
226         x=p[p[x].tp].f;
227     }
228     if(p[x].dp>p[y].dp)
229         std::swap(x,y);
230     return x;
231 }
232 int Dis(int x,int y)
233 {
234     int z=Lca(x,y);
235     return p[x].dis+p[y].dis-2*p[z].dis;
236 }
237 void grc_dfs(int x,int f)
238 {
239     sta[++top]=x;
240     p[x].wgt=1;
241     int maxs=-1;
242     for(int i=p[x].hd;i;i=e[i].lst)
243     {
244         int to=e[i].twd;
245         if(to==f||p[to].vis)
246             continue;
247         grc_dfs(to,x);
248         p[x].wgt+=p[to].wgt;
249         if(maxs<p[to].wgt)
250             maxs=p[to].wgt;
251     }
252     maxs=std::max(maxs,size-p[x].wgt);
253     if(maxs<maxsize)
254     {
255         root=x;
256         maxsize=maxs;
257     }
258     return ;
259 }
260 void bin_dfs(int x,int f)
261 {
262     p[x].fa=f;
263     p[x].vis=true;
264     int tmp=size;
265     if(f)
266         for(int i=1;i<=top;i++)
267             Insert(p[x].cnrt,Dis(f,sta[i]));
268     Insert(p[x].dcrt,0);
269     for(int i=p[x].hd;i;i=e[i].lst)
270     {
271         int to=e[i].twd;
272         if(p[to].vis)
273             continue;
274         root=0;
275         top=0;
276         if(p[to].wgt<p[x].wgt)
277             size=p[to].wgt;
278         else
279             size=tmp-p[x].wgt;
280         maxsize=0x3f3f3f3f;
281         grc_dfs(to,to);
282         int rt=root;
283         bin_dfs(root,x);
284         Insert(p[x].dcrt,Maxval(p[rt].cnrt));
285     }
286     Insert(ansroot,Chain(p[x].dcrt));
287     return ;
288 }
289 void Update(int oldans,int newans)
290 {
291     if(oldans==newans)
292         return ;
293     Delete(ansroot,oldans);
294     Insert(ansroot,newans);
295     return ;
296 }
297 void Insert(int x)
298 {
299     int la,na,lc,nc;
300     la=Chain(p[x].dcrt);
301     Insert(p[x].dcrt,0);
302     na=Chain(p[x].dcrt);
303     Update(la,na);
304     for(int i=x;p[i].fa;i=p[i].fa)
305     {
306         lc=Maxval(p[i].cnrt);
307         Insert(p[i].cnrt,Dis(x,p[i].fa));
308         nc=Maxval(p[i].cnrt);
309         if(lc==nc)
310             continue;
311         la=Chain(p[p[i].fa].dcrt);
312         if(lc!=-0x3f3f3f3f)
313             Delete(p[p[i].fa].dcrt,lc);
314         Insert(p[p[i].fa].dcrt,nc);
315         na=Chain(p[p[i].fa].dcrt);
316         Update(la,na);
317     }
318     return ;
319 }
320 void Delete(int x)
321 {
322     int la,na,lc,nc;
323     la=Chain(p[x].dcrt);
324     Delete(p[x].dcrt,0);
325     na=Chain(p[x].dcrt);
326     Update(la,na);
327     for(int i=x;p[i].fa;i=p[i].fa)
328     {
329         lc=Maxval(p[i].cnrt);
330         Delete(p[i].cnrt,Dis(x,p[i].fa));
331         nc=Maxval(p[i].cnrt);
332         if(lc==nc)
333             continue;
334         la=Chain(p[p[i].fa].dcrt);
335         Delete(p[p[i].fa].dcrt,lc);
336         if(nc!=-0x3f3f3f3f)
337             Insert(p[p[i].fa].dcrt,nc);
338         na=Chain(p[p[i].fa].dcrt);
339         Update(la,na);
340     }
341     return ;
342 }
343 int main()
344 {
345     scanf("%d",&n);
346     for(int i=1;i<n;i++)
347     {
348         int a,b;
349         scanf("%d%d",&a,&b);
350         ade(a,b);
351         ade(b,a);
352     }
353     Basic_dfs(1,1);
354     Build_dfs(1,1);
355     root=0;
356     size=n;
357     maxsize=0x3f3f3f3f;
358     grc_dfs(1,1);
359     bin_dfs(root,0);
360     scanf("%d",&m);
361     while(m--)
362     {
363         scanf("%s",cmd+1);
364         if(cmd[1]=='G')
365         {
366             if(del==n)
367                 puts("-1");
368             else if(del==n-1)
369                 puts("0");
370             else
371                 printf("%d\n",Maxval(ansroot));
372         }else{
373             int x;
374             scanf("%d",&x);
375             p[x].val^=1;
376             if(p[x].val)
377             {
378                 Delete(x);
379                 del++;
380             }else{
381                 Insert(x);
382                 del--;
383             }
384         }
385     }
386     return 0;
387 }

 

posted @ 2018-12-22 10:35  Unstoppable728  阅读(227)  评论(0编辑  收藏  举报