bzoj:1095: [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
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
3
3
4
写的时候感觉脑子要炸了……代码会很丑……
是正常三层堆的做法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<queue> #include<cstdio> #include<algorithm> #define MN 100001 using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } struct na{ int x,y,z,ne; }b[2*MN],bb[1700001],bv[MN]; int n,m,ma,la[MN],num=0,fa[MN],s[MN],lla[MN],vla[MN],size,root,nnum=0,vnum=0,mmh,ha[MN],ppp=0,nm=0; bool v[MN],p[MN]; struct nma{ int x,fr; bool operator < (nma a)const{return x<a.x;} }; nma m_a(int x,int fr){nma a;a.x=x;a.fr=fr;return a;} const int INF=1e9; priority_queue <nma> q[MN],qv[MN],all; inline void in(int x,int y){b[++num].y=y;b[num].ne=la[x];la[x]=num;} inline void add(int u,int x,int y,int z){bb[++nnum].x=x;bb[nnum].y=y;bb[nnum].z=z;bb[nnum].ne=lla[u];lla[u]=nnum;} inline void newin(int x,int y){bv[++vnum].y=y;bv[vnum].ne=vla[x];vla[x]=vnum;} inline void gs(int x,int f){ int u=0;s[x]=1; for (int i=la[x];i;i=b[i].ne) if (!v[b[i].y]&&b[i].y!=f) gs(b[i].y,x),s[x]+=s[b[i].y],u=u>s[b[i].y]?u:s[b[i].y]; if (u<size-s[x]) u=size-s[x]; if (u<ma) root=x,ma=u; } inline void ch(int x){ for (int i=vla[x];i;i=bv[i].ne) if (!q[bv[i].y].empty())qv[x].push(m_a(q[bv[i].y].top().x,bv[i].y)); } inline void cg(int x){ while(!qv[x].empty()){if (!q[qv[x].top().fr].empty()) if (qv[x].top().x==q[qv[x].top().fr].top().x) break;qv[x].pop();} if (qv[x].empty()){ha[x]=-1;return;} nma mmh=qv[x].top();int u=mmh.x; qv[x].pop(); while(!qv[x].empty()){if (qv[x].top().fr!=mmh.fr)if (!q[qv[x].top().fr].empty()) if (qv[x].top().x==q[qv[x].top().fr].top().x) break;qv[x].pop();} if (qv[x].empty()){if (!p[x]) {ha[x]=-1;qv[x].push(mmh);return;}}else u+=qv[x].top().x; qv[x].push(mmh); ha[x]=u; all.push(m_a(u,x)); while(!all.empty()){if (all.top().x==ha[all.top().fr]) break;all.pop();} } inline void gx(int x,int y){ mmh=q[x].top().x; while(!q[x].empty()){if (p[q[x].top().fr]) break;q[x].pop();} if (!q[x].empty()) if (q[x].top().x!=mmh) qv[y].push(m_a(q[x].top().x,x)); while(!qv[y].empty()){if (!q[qv[y].top().fr].empty()) if (qv[y].top().x==q[qv[y].top().fr].top().x) break;qv[y].pop();} } inline void dfs(int x,int f,int dis){ if (dis==1) mmh=++nm,newin(root,nm); if (f) add(x,mmh,root,dis),q[mmh].push(m_a(dis,x)); for (int i=la[x];i;i=b[i].ne) if (b[i].y!=f&&(!v[b[i].y])) dfs(b[i].y,x,dis+1); } inline void work(int x,int siz,int f){ size=siz;ma=INF;gs(x,0);x=root; dfs(x,0,0);ha[x]=-1;ch(x);cg(x);v[x]=1; for (int i=la[x];i;i=b[i].ne) if (!v[b[i].y]) work(b[i].y,s[b[i].y],x); } inline int min(int x,int y){return x>y?y:x;} char cc[10]; int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int x,y;register int j; ppp=n=read(); for (int i=1;i<n;i++) x=read(),y=read(),in(x,y),in(y,x); for (int i=1;i<=n;i++) p[i]=1; work(1,n,0); n=read(); while(n--){ scanf("%s",cc); if (cc[0]=='C'){ if (p[y=read()]^=1) for (j=lla[y];j;j=bb[j].ne){ if (q[bb[j].x].empty()) mmh=-1;else mmh=q[bb[j].x].top().x; q[bb[j].x].push(m_a(bb[j].z,y)); while(!q[x].empty()){if (p[q[x].top().fr]) break;q[x].pop();} if (q[bb[j].x].top().x!=mmh) qv[bb[j].y].push(m_a(q[bb[j].x].top().x,bb[j].x)),cg(bb[j].y); }else for (j=lla[y];j;j=bb[j].ne) gx(bb[j].x,bb[j].y),cg(bb[j].y);cg(y); if (p[y]) ppp++;else ppp--; } else if (!ppp)printf("-1\n");else if (ppp==1) printf("0\n");else{ while(!all.empty()){if (all.top().x==ha[all.top().fr]) break;all.pop();} printf("%d\n",all.top().x); } } }