码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习

时间:2017-05-21 21:48:54      阅读:278      评论:0      收藏:0      [点我收藏+]

标签:names   clu   固定   实现   name   复杂度   erase   暴力   top   

好迷啊。。。感觉动态点分治就是个玄学,蜜汁把树的深度缩到logn

(静态)点分治大概是递归的时候分类讨论:

  1.答案经过当前点,暴力(雾)算

  2.答案不经过当前点,继续递归

由于原树可以长的奇形怪状(菊花啊、、链啊、、扫把啊、、)这就导致各种方法都会被卡

于是通过每次找重心保证最大深度

动态怎么解决呢?

不妨考虑线段树是二分的固态版本(只可意会),那么我们把每次找到的重心固定下来长成一棵树就可以把点分治凝固(不可言传)

原来点分治该维护什么现在就维护什么。。。

(事实上我并没有写过静态点分治。。。好气啊╮(╯▽╰)╭)

我居然一度认为新建的树的节点要连到所在子树外一定要经过该子树的根。。。太思博了

实现细节:

  1.有一个带删堆,直接拉了板子(拉了才知道实现那么简单,本来以为手打)

  2.lca以前习惯rmq(复杂度优异就是自信),现在改成倍增了(可能是之前写了个长链剖分的缘故)

  1 #include<bits/stdc++.h>
  2 using namespace std;  
  3 const int Mn=100005;  
  4 int cnt=0,h[Mn],n,m,vst[Mn],maxx,tg,s[Mn],sz,prt[Mn];  
  5 int d[Mn],p[Mn][21],co[Mn];  
  6 struct Priority_Queue{  
  7     priority_queue<int> q,del;  
  8     void push(int x)
  9     {q.push(x);}  
 10     void erase(int x){del.push(x);}  
 11     int top()
 12     {  
 13         while(del.size()&&del.top()==q.top())  
 14             {del.pop();q.pop();}  
 15         return q.top();  
 16     }  
 17     void Pop()
 18     {  
 19         while(del.size()&&del.top()==q.top())  
 20             del.pop(),q.pop();
 21         q.pop();  
 22     }  
 23     int sec_top()
 24     {
 25         int tmp=top();Pop();  
 26         int se=top();push(tmp);  
 27         return se;  
 28     }  
 29     int size()
 30     {
 31         return q.size()-del.size();
 32     }  
 33 }c[Mn],f[Mn],ans;  
 34 struct Edge{int to,next;}w[Mn*2];  
 35 void add(int x,int y)
 36 {w[++cnt]=(Edge){y,h[x]};h[x]=cnt;}  
 37 void build(int x,int fa)
 38 {
 39     p[x][0]=fa;d[x]=d[fa]+1;
 40     for(int i=1;p[x][i-1];i++)
 41         p[x][i]=p[p[x][i-1]][i-1];
 42     for(int i=h[x];i;i=w[i].next)
 43     if(w[i].to!=fa)
 44         build(w[i].to,x);
 45 }  
 46 void Insert(Priority_Queue &s){  
 47      if(s.size()>1)ans.push(s.top()+s.sec_top());  
 48 }  
 49 void Erase(Priority_Queue &s){  
 50      if(s.size()>1)ans.erase(s.top()+s.sec_top());  
 51 }  
 52 void DP(int x,int fa)
 53 {
 54      int j,y;s[x]=1;
 55      for(j=h[x];j;j=w[j].next)
 56      {  
 57         y=w[j].to;  
 58         if(y==fa||vst[y])continue;  
 59         DP(y,x);  
 60         s[x]+=s[y];  
 61      }  
 62 }  
 63 void Biggest(int x,int fa){  
 64      int j,y,mx=0;  
 65      for(j=h[x];j;j=w[j].next){  
 66         y=w[j].to;  
 67         if(y==fa||vst[y])continue;  
 68         Biggest(y,x);  
 69         mx=max(mx,s[y]);  
 70      }  
 71      if(maxx>max(mx,sz-s[x])){  
 72         maxx=max(mx,sz-s[x]);  
 73         tg=x;  
 74      }  
 75 }  
 76 int gg(int x)//get G
 77 {  
 78     maxx=n+1;tg=0;  
 79     DP(x,0);
 80     sz=s[x];  
 81     Biggest(x,0);  
 82     return tg;  
 83 }  
 84 int LCA(int x,int y){  
 85     int j;  
 86     if(d[x]<d[y])swap(x,y);  
 87     for(j=20;j>=0;j--)  
 88       if(d[p[x][j]]>=d[y])x=p[x][j];  
 89     if(x==y)return x;  
 90     for(j=20;j>=0;j--)  
 91       if(p[x][j]!=p[y][j])  
 92        {x=p[x][j];y=p[y][j];}  
 93     return p[x][0];  
 94 }  
 95 int Dis(int x,int y){return d[x]+d[y]-2*d[LCA(x,y)];}  
 96 void work(int x,int fa,int Gra){  
 97      int j,y;  
 98      f[Gra].push(Dis(x,prt[Gra]));  
 99      for(j=h[x];j;j=w[j].next){  
100         y=w[j].to;  
101         if(y==fa||vst[y])continue;  
102         work(y,x,Gra);  
103      }  
104 }  
105 int mzz(int x,int fa)
106 {  
107     int j,y,G,Gy;  
108     G=gg(x);prt[G]=fa;  
109     work(G,0,G);
110     vst[G]=1; 
111     c[G].push(0);  
112     for(j=h[G];j;j=w[j].next)
113     {
114         y=w[j].to;  
115         if(!vst[y]){  
116             Gy=mzz(y,G);  
117             c[G].push(f[Gy].top());  
118         }  
119     }  
120     Insert(c[G]);  
121     return G;  
122 }  
123 void Light(int x){  
124      Erase(c[x]);  
125      c[x].erase(0);  
126      Insert(c[x]);  
127      for(int y=x;prt[y];y=prt[y]){  
128         Erase(c[prt[y]]);  
129         if(f[y].size())c[prt[y]].erase(f[y].top());  
130         f[y].erase(Dis(x,prt[y]));  
131         if(f[y].size())c[prt[y]].push(f[y].top());  
132         Insert(c[prt[y]]);  
133      }  
134 }  
135 void LiOut(int x){  
136      Erase(c[x]);  
137      c[x].push(0);  
138      Insert(c[x]);  
139      for(int y=x;prt[y];y=prt[y]){  
140         Erase(c[prt[y]]);  
141         if(f[y].size())c[prt[y]].erase(f[y].top());  
142         f[y].push(Dis(x,prt[y]));  
143         if(f[y].size())c[prt[y]].push(f[y].top());  
144         Insert(c[prt[y]]);  
145      }  
146 }  
147 void solve(){  
148      int i,x;char ch[5];  
149      cnt=n;  
150      scanf("%d",&m);  
151      for(i=1;i<=m;i++){  
152         scanf("%s",ch);  
153         if(ch[0]==G){  
154           if(cnt<=1)printf("%d\n",cnt-1);  
155           else printf("%d\n",ans.top());  
156         }  
157         else{  
158             scanf("%d",&x);  
159             if(!co[x]){cnt--;Light(x);co[x]=1;}  
160             else{cnt++;LiOut(x);co[x]=0;}  
161         }  
162      }  
163 }  
164 int main()
165 {  
166     scanf("%d",&n);int x,y;
167     for(int i=1;i<n;i++)
168         scanf("%d%d",&x,&y),
169         add(x,y),add(y,x);
170     build(1,0);mzz(1,0);
171     solve();
172     return 0;
173 }  

 

bzoj1095: [ZJOI2007]Hide 捉迷藏 动态点分治学习

标签:names   clu   固定   实现   name   复杂度   erase   暴力   top   

原文地址:http://www.cnblogs.com/wanglichao/p/6885797.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!