1. 程式人生 > >bzoj1095: [ZJOI2007]Hide 捉迷藏 動態點分治學習

bzoj1095: [ZJOI2007]Hide 捉迷藏 動態點分治學習

由於 print pac include void get || nbsp big

好迷啊。。。感覺動態點分治就是個玄學,蜜汁把樹的深度縮到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 捉迷藏 動態點分治學習