今天的木留又在打摆子QAQ但是木留还是要努力变强ovo

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

HINT

对于100%的数据, N ≤100000, M ≤500000。

 
我有多久没碰博客了ojz大概是最近太怠惰了吧……
然后最近在学点分治,Zn_H神犇就唆使我做这道题咯QAQ
还是太神了看了题解想了好久才懂……
 
先建一个重心树,这个的意思就是,通过点分治的过程,找到每一个层的重心,然后用这些重心上一层重心连下一层这样建一个树。
这样可以保证重心树深度小于等于logn。
然后对于每个点建两个堆,
第一个堆s1表示:该点的所有子树的点到其重心树上的父亲的距离。
第二个堆s2表示:该点在重心树上的所有子树的点的堆s1的top值。
再用一个ans堆记录每个点的堆s2上最大值和次大值之和,询问答案即取top即可。
 
删除操作和插入操作就对这两个堆进行修改。
可以这么理解:
每次修改后我们可以在每次向上更新时,先删去在ans堆的中的目前点的重心树上父亲的s2堆的最大值和次大值之和,再删去目前点的重心树上父亲的s2堆中,目前点的s1堆的top值。然后操作,插入/删除目前点的重心树上父亲到x(操作的那个点)的距离。最后再插入目前点的重心树上父亲的s2堆中,目前点的s1堆的top值,再在ans堆中插入目前点的重心树上父亲的s2堆的最大值和次大值之和。(各种拗口总之看代码其实很好懂)
 
代码这样QAQ(看有dalao只写了120+行,佩服ojz)
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<algorithm>
  8 using namespace std;
  9 #define maxm 500005
 10 #define maxn 100100
 11 
 12 int read()
 13 {
 14     int f=1,p=0;
 15     char c=getchar();
 16     while (c<'0'||c>'9'){if (c=='-')f=-1;c=getchar();}
 17     while (c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
 18     return f*p;
 19 }
 20 
 21 int n,m,cnt=0,all,rt,T=0,tot=0;
 22 int son[maxn],f[maxn],fa[maxn],pos[maxn],dep[maxn],a[maxn<<1][20];
 23 int lg2[maxn<<1],head[maxn],can[maxn];
 24 bool cdt[maxn];
 25 struct edge{int u,v,next;}e[maxn<<1];
 26 
 27 struct node
 28 {
 29     priority_queue<int> heap,delmark;
 30 
 31     void ins(int x)
 32     {heap.push(x);}
 33     void del(int x)
 34     {delmark.push(x);}
 35     void POP()
 36     {
 37         while (delmark.size()&&delmark.top()==heap.top())
 38         delmark.pop(),heap.pop();
 39         heap.pop();
 40     }
 41     int TOP()
 42     {
 43         while (delmark.size()&&delmark.top()==heap.top())
 44         delmark.pop(),heap.pop();
 45         return heap.top();
 46     }
 47     int sdTOP()
 48     {
 49         int ls=TOP();POP();
 50         int ret=TOP();ins(ls);
 51         return ret;
 52     }
 53     int SIZE()
 54     {
 55         return heap.size()-delmark.size();
 56     }
 57 }s1[maxn],s2[maxn],ans;
 58 
 59 void addedge(int u,int v)
 60 {
 61     cnt++;e[cnt].u=u;e[cnt].v=v;
 62     e[cnt].next=head[u];head[u]=cnt;
 63 }
 64 void getroot(int x,int pa)
 65 {
 66     son[x]=1;f[x]=0;
 67     for (int i=head[x];i;i=e[i].next)
 68     {
 69         int y=e[i].v;
 70         if (can[y]||y==pa) continue;
 71         getroot(y,x);
 72         son[x]+=son[y];
 73         if (son[y]>f[x]) f[x]=son[y];
 74     }
 75     if (all-son[x]>f[x]) f[x]=all-son[x];
 76     if (f[x]<f[rt]) rt=x;
 77 }
 78 void dfs(int x,int pa,int dep,node &s)
 79 {
 80     s.ins(dep);
 81     for (int i=head[x];i;i=e[i].next)
 82     {
 83         int y=e[i].v;
 84         if (can[y]||y==pa) continue;
 85         dfs(y,x,dep+1,s);
 86     }
 87 }
 88 void insert(node &s)
 89 {
 90     if (s.SIZE()>=2)
 91     {
 92         int tmp=s.TOP()+s.sdTOP();
 93         ans.ins(tmp);
 94     }
 95 }
 96 void erase(node &s)
 97 {
 98     if (s.SIZE()>=2)
 99     {
100         int tmp=s.TOP()+s.sdTOP();
101         ans.del(tmp);
102     }
103 }
104 void work(int x)
105 {
106     can[x]=1;
107     s2[x].ins(0);
108     for (int i=head[x];i;i=e[i].next)
109     {
110         int y=e[i].v;
111         if (can[y]) continue;
112         node s;
113         dfs(y,x,1,s);
114         all=son[y];f[rt=0]=n+1;
115         getroot(y,0);
116         int ls=rt;work(rt);
117         fa[ls]=x;s1[ls]=s;
118         s2[x].ins(s.TOP());
119     }
120     insert(s2[x]);
121 }
122 void getdep(int x,int pa)
123 {
124     a[pos[x]=++T][0]=dep[x]=dep[pa]+1;
125     for (int i=head[x];i;i=e[i].next)
126     {
127         int y=e[i].v;
128         if (y==pa) continue;
129         getdep(y,x);
130         a[++T][0]=dep[x];
131     }
132 }
133 int lcadep(int x,int y)
134 {
135     x=pos[x],y=pos[y];
136     if (x>y) swap(x,y);
137     int ls=lg2[y-x+1];
138     return min(a[x][ls],a[y-(1<<ls)+1][ls]);
139 }
140 int dis(int x,int y)
141 {
142     return dep[x]+dep[y]-2*lcadep(x,y);
143 }
144 void turnoff(int x)
145 {
146     erase(s2[x]);
147     s2[x].ins(0);
148     insert(s2[x]);
149     for (int i=x;fa[i];i=fa[i])
150     {
151         erase(s2[fa[i]]);
152         if (s1[i].SIZE())
153         s2[fa[i]].del(s1[i].TOP());
154         s1[i].ins(dis(fa[i],x));
155         if (s1[i].SIZE())
156         s2[fa[i]].ins(s1[i].TOP());
157         insert(s2[fa[i]]);
158     }
159 }
160 void turnon(int x)//del
161 {
162     erase(s2[x]);
163     s2[x].del(0);
164     insert(s2[x]);
165     for (int i=x;fa[i];i=fa[i])
166     {
167         erase(s2[fa[i]]);
168         if (s1[i].SIZE())
169         s2[fa[i]].del(s1[i].TOP());
170         s1[i].del(dis(fa[i],x));
171         if (s1[i].SIZE())
172         s2[fa[i]].ins(s1[i].TOP());
173         insert(s2[fa[i]]);
174     }
175 }
176 
177 int main()
178 {
179     freopen("hide.in","r",stdin);
180     freopen("hide.out","w",stdout);
181     n=read();
182     for (int i=1;i<n;i++) 
183     {
184         int u=read(),v=read();
185         addedge(u,v);
186         addedge(v,u);
187     }
188     f[rt=0]=n+1;all=n;
189     getroot(1,0);work(rt);getdep(1,0);
190     for (int i=2;i<=T;i++)
191     lg2[i]=lg2[i>>1]+1;
192     for (int j=1;j<=lg2[T];j++)
193     for (int i=1;i+(1<<j)-1<=T;i++)
194     a[i][j]=min(a[i][j-1],a[i+(1<<j-1)][j-1]);
195     //0是关灯,1是开灯
196     m=read();tot=n;
197     char op[10];
198     for (int i=1;i<=m;i++)
199     {
200         scanf("%s",op);
201         if (op[0]=='C')
202         {
203             int ch=read();
204             if (cdt[ch])
205             {
206                 tot++;cdt[ch]=0;
207                 turnoff(ch);
208             }
209             else
210             {
211                 tot--;cdt[ch]=1;
212                 turnon(ch);
213             }
214         }
215         else
216         {
217             if (tot<=1) printf("%d\n",tot-1);
218             else printf("%d\n",ans.TOP());
219         }
220     }
221     fclose(stdin);
222     fclose(stdout);
223     return 0;
224 }

就酱w总算是搞完这题了天哪噜。

 
posted @ 2017-05-23 19:43  木留木留木  阅读(137)  评论(0编辑  收藏  举报