Bzoj1095 [ZJOI2007]Hide 捉迷藏
Submit: 3369 Solved: 1383
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
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
3
3
4
HINT
对于100%的数据, N ≤100000, M ≤500000。
Source
动态点分治
看到还有种线段树做法跑得飞快,姑且mark下,日后研究
先根据原树建出点分治树,保证树深度小于logn
在点分治树上处理问题,维护三种堆:1、每个结点的子树中,该结点到子节点的距离;2、每个结点的子结点的1种堆堆顶;3、每个结点的2种堆的最大值和次大值之和
记录每层祖先,改变某结点存在性时,暴力上溯最多logn次即可。
3号堆的堆顶就是答案。
STL大法好,priority_queue可以省不少力
↑然而即使“省了不少力“,还是花了一上午才调对。
↑原因是试图一边建树一边更新信息,然后代码太乱了,人又困,傻傻找不出错。最后干脆重构代码,老实建完树再一个个更新结点信息,又调了一阵子终于A了
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 using namespace std; 10 const int mxn=100010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct edge{int v,nxt;}e[mxn<<1]; 18 int hd[mxn],mct=0; 19 void add_edge(int u,int v){ 20 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 21 } 22 int n,m; 23 int light[mxn]; 24 struct Heap{ 25 priority_queue<int>hp,dl; 26 void push(int x){hp.push(x);} 27 void del(int x){dl.push(x);} 28 int size(){return hp.size()-dl.size();} 29 void pop(){ 30 while(!dl.empty() && dl.top()==hp.top()){dl.pop();hp.pop();} 31 hp.pop(); 32 } 33 int top(){ 34 while(!dl.empty() && dl.top()==hp.top()){dl.pop();hp.pop();} 35 return hp.top(); 36 } 37 int second(){ 38 int x=top();pop(); int y=top();push(x); 39 return y; 40 } 41 }s1[mxn],s2[mxn],s; 42 void insert(Heap &p){ 43 if(p.size()>=2){ 44 int tmp=p.top()+p.second(); 45 s.push(tmp); 46 } 47 return; 48 } 49 void Erase(Heap &p){ 50 if(p.size()>=2){ 51 int tmp=p.top()+p.second(); 52 s.del(tmp); 53 } 54 return; 55 } 56 int sz[mxn],mc[mxn],rt,smm; 57 bool vis[mxn]; 58 void DFS_sz(int u,int fa){ 59 sz[u]=1;mc[u]=0; 60 for(int i=hd[u];i;i=e[i].nxt){ 61 int v=e[i].v;if(vis[v] || v==fa)continue; 62 DFS_sz(v,u); 63 sz[u]+=sz[v]; 64 mc[u]=max(mc[u],sz[v]); 65 } 66 mc[u]=max(mc[u],smm-mc[u]); 67 if(mc[u]<mc[rt])rt=u; 68 return; 69 } 70 int f[mxn][20],dis[mxn][20]; 71 int dep[mxn]; 72 void getship(int u,int fa,int an,int d){ 73 // printf("GS:u:%d fa:%d an:%d d:%d\n",u,fa,an,d); 74 for(int i=hd[u];i;i=e[i].nxt){ 75 int v=e[i].v;if(vis[v] || v==fa)continue; 76 f[v][++dep[v]]=an; 77 dis[v][dep[v]]=d; 78 getship(v,u,an,d+1); 79 } 80 return; 81 } 82 void solve(int x,int ff){ 83 // printf("Rt:%d\n",x); 84 vis[x]=1; 85 getship(x,0,x,1); 86 for(int i=hd[x];i;i=e[i].nxt){ 87 if(vis[e[i].v])continue;int v=e[i].v; 88 rt=0;smm=sz[v]; 89 DFS_sz(v,0); 90 solve(rt,x); 91 } 92 return; 93 } 94 void update(int x,int mode){ 95 // printf("update:%d mode:%d\n",x,mode); 96 Erase(s2[x]); 97 if(!mode){s2[x].push(0);insert(s2[x]);} 98 else{s2[x].del(0);insert(s2[x]);} 99 for(int i=dep[x];i>1;i--){ 100 // printf("anc%d : %d dis:%d\n",i,f[x][i],dis[x][i]); 101 if(!mode){//关灯 102 Erase(s2[f[x][i-1]]); 103 104 if(s1[f[x][i]].size()) s2[f[x][i-1]].del(s1[f[x][i]].top()); 105 s1[f[x][i]].push(dis[x][i-1]); 106 if(s1[f[x][i]].size()) s2[f[x][i-1]].push(s1[f[x][i]].top()); 107 108 insert(s2[f[x][i-1]]); 109 } 110 else{//开灯 111 Erase(s2[f[x][i-1]]); 112 113 if(s1[f[x][i]].size()) s2[f[x][i-1]].del(s1[f[x][i]].top()); 114 s1[f[x][i]].del(dis[x][i-1]); 115 if(s1[f[x][i]].size()) s2[f[x][i-1]].push(s1[f[x][i]].top()); 116 117 insert(s2[f[x][i-1]]); 118 } 119 } 120 return; 121 } 122 int lcnt=0; 123 int Que(){if(lcnt>1 && s.size())return s.top();else return lcnt-1;} 124 int main(){ 125 int i,j,u,v; 126 n=read(); 127 for(i=1;i<n;i++){ 128 u=read();v=read(); 129 add_edge(u,v); 130 add_edge(v,u); 131 } 132 smm=n; 133 mc[rt=0]=1e8; 134 DFS_sz(1,0); 135 solve(rt,0); 136 lcnt=n; 137 for(i=1;i<=n;i++)f[i][++dep[i]]=i; 138 for(i=1;i<=n;i++)update(i,0); 139 m=read(); 140 char op[5]; 141 while(m--){ 142 scanf("%s",op); 143 if(op[0]=='C'){ 144 u=read(); 145 light[u]^=1; 146 if(light[u])lcnt--; 147 else lcnt++; 148 update(u,light[u]); 149 } 150 else{ 151 // printf("G!!\n"); 152 int ans=Que(); 153 printf("%d\n",ans); 154 } 155 } 156 return 0; 157 }