您的位置:首页 > 其它

BZOJ1095: [ZJOI2007]Hide 捉迷藏

2015-07-06 17:06 239 查看

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。

妈妈我终于写完动态树分治了。
code几乎抄了一遍黄学长的。
看这篇吧:http://hzwer.com/5247.html

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=200010;
struct Heap {
priority_queue<int> A,del;
void push(int x) {A.push(x);}
void erase(int x) {del.push(x);}
void pop() {
while(del.size()&&A.top()==del.top()) A.pop(),del.pop();
A.pop();
}
int top() {
while(del.size()&&A.top()==del.top()) A.pop(),del.pop();
return !A.size()?0:A.top();
}
int size() {return A.size()-del.size();}
int stop() {
if(size()<2) return 0;
int t1=top();pop();
int t2=top();push(t1);
return t2;
}
}A,B[maxn],C[maxn];
int n,m,clo[maxn],first[maxn],next[maxn],to[maxn],es;
void AddEdge(int u,int v) {
to[++es]=v;next[es]=first[u];first[u]=es;
to[++es]=u;next[es]=first[v];first[v]=es;
}
int Log[maxn],mn[19][maxn],dep[maxn],pos[maxn],dfs_clock;
void dfs(int x,int fa) {
mn[0][++dfs_clock]=dep[x];pos[x]=dfs_clock;
ren if(to[i]!=fa) {
dep[to[i]]=dep[x]+1;
dfs(to[i],x);
mn[0][++dfs_clock]=dep[x];
}
}
void init() {
Log[0]=-1;rep(1,200000) Log[i]=Log[i>>1]+1;
for(int i=1;(1<<i)<=dfs_clock;i++)
for(int j=1;j+(1<<i)-1<=dfs_clock;j++)
mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]);
}
int dist(int x,int y) {
int ans=dep[x]+dep[y];
x=pos[x];y=pos[y];if(x>y) swap(x,y);
int k=Log[y-x+1];
return ans-2*min(mn[k][x],mn[k][y-(1<<k)+1]);
}
int root,size,vis[maxn],f[maxn],s[maxn];
void getroot(int x,int fa) {
int maxs=0;s[x]=1;
ren if(to[i]!=fa&&!vis[to[i]]) getroot(to[i],x),maxs=max(maxs,s[to[i]]),s[x]+=s[to[i]];
f[x]=max(maxs,size-s[x]);
if(f[root]>f[x]) root=x;
}
int fa[maxn];
void solve(int x,int F) {
fa[x]=F;vis[x]=1;
ren if(!vis[to[i]]) {
size=f[0]=s[to[i]];getroot(to[i],root=0);
solve(root,x);
}
}
void turn_off(int u,int v) {
if(u==v) {
B[u].push(0);
if(B[u].size()==2) A.push(B[u].top());
}
if(!fa[u]) return;
int f=fa[u],D=dist(f,v),tmp=C[u].top();C[u].push(D);
if(D>tmp) {
int mx=B[f].top()+B[f].stop(),size=B[f].size();
if(tmp) B[f].erase(tmp);
B[f].push(D);
int now=B[f].top()+B[f].stop();
if(now>mx) {
if(size>=2) A.erase(mx);
if(B[f].size()>=2) A.push(now);
}
}
turn_off(f,v);
}
void turn_on(int u,int v) {
if(u==v) {
if(B[u].size()==2) A.erase(B[u].top());
B[u].erase(0);
}
if(!fa[u]) return;
int f=fa[u],D=dist(f,v),tmp=C[u].top();
C[u].erase(D);
if(D==tmp) {
int mx=B[f].top()+B[f].stop(),size=B[f].size();
B[f].erase(D);
if(C[u].top()) B[f].push(C[u].top());
int now=B[f].top()+B[f].stop();
if(now<mx) {
if(size>=2) A.erase(mx);
if(B[f].size()>=2) A.push(now);
}
}
turn_on(f,v);
}
int main() {
n=read();
rep(2,n) AddEdge(read(),read());
dfs(1,0);init();
size=f[0]=n;getroot(1,root=0);
solve(root,0);
rep(1,n) clo[i]=1,C[i].push(0),turn_off(i,i);
char ch[2];
m=read();int cnt=n;
while(m--) {
scanf("%s",ch);
if(ch[0]=='G') printf("%d\n",cnt<2?-1:A.top());
else {
int x=read();
if(clo[x]) turn_on(x,x),cnt--;
else turn_off(x,x),cnt++;
clo[x]^=1;
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: