1095: [ZJOI2007]Hide 捉迷藏
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 2638 Solved: 1088
[ Submit][ Status][ Discuss]
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
HINT
对于100%的数据, N ≤100000, M ≤500000。
Source
定义suf_minus(S) = max{a' - b'|S'以黑点开头,是S的一个后缀}
定义pre_plus(S) = max{a' + b'|S'以黑点结尾,是S的一个前缀}
定义pre_minus(S) = max{b' - a'|S'以黑点结尾,是S的一个前缀}
a - b = a1 - b1 + a2 - b2
b - a = b1 - a1 + b2 - a2
suf_plus(s) = max{suf_plus(sr),suf_minus(sl) + c + d,suf_plus(sl) - c + d}
suf_minus(s) = max{suf_minus(sr),suf_minus(sl) + c - d}
pre_plus(s) = max{pre_plus(sl),a - b + pre_plus(sr),a + b + pre_minus(sr)}
pre_minus(s) = max{pre_minus(sl),b - a + pre_minus(sr)}
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 3E5 + 10;
const int T = 10;
const int INF = 1E5;
int n,m,dfs_clock,Dis[maxn*T],suf_plus[maxn*T],suf_minus[maxn*T],Now[maxn]
,pre_plus[maxn*T],pre_minus[maxn*T],A[maxn*T],B[maxn*T],pos[maxn];
vector <int> v[maxn];
void maintain(int o)
{
int lc = o<<1,rc = o<<1|1;
if (B[rc] >= A[lc]) B[o] = B[lc] + B[rc] - A[lc],A[o] = A[rc];
else A[o] = A[lc] - B[rc] + A[rc],B[o] = B[lc];
Dis[o] = max(Dis[lc],Dis[rc]);
Dis[o] = max(Dis[o],suf_plus[lc] + pre_minus[rc]);
Dis[o] = max(Dis[o],suf_minus[lc] + pre_plus[rc]);
suf_plus[o] = max(suf_plus[rc],suf_minus[lc] + B[rc] + A[rc]);
suf_plus[o] = max(suf_plus[o],suf_plus[lc] - B[rc] + A[rc]);
suf_minus[o] = max(suf_minus[rc],suf_minus[lc] + B[rc] - A[rc]);
pre_plus[o] = max(pre_plus[lc],B[lc] - A[lc] + pre_plus[rc]);
pre_plus[o] = max(pre_plus[o],B[lc] + A[lc] + pre_minus[rc]);
pre_minus[o] = max(pre_minus[lc],A[lc] - B[lc] + pre_minus[rc]);
}
void Insert(int o,int l,int r,int posi,int typ)
{
if (l == r) {
if (typ == 0) {
A[o] = 1; Dis[o] = -INF;
suf_plus[o] = suf_minus[o] = -INF;
pre_plus[o] = pre_minus[o] = -INF;
}
else if (typ == 1) {
B[o] = 1; Dis[o] = -INF;
suf_plus[o] = suf_minus[o] = -INF;
pre_plus[o] = pre_minus[o] = -INF;
}
else Dis[o] = -INF;
return;
}
int mid = (l + r) >> 1;
if (posi <= mid) Insert(o<<1,l,mid,posi,typ);
else Insert(o<<1|1,mid+1,r,posi,typ);
maintain(o);
}
void Dfs(int x,int from)
{
Insert(1,1,3*n,++dfs_clock,0);
pos[x] = ++dfs_clock;
Insert(1,1,3*n,pos[x],2);
for (int i = 0; i < v[x].size(); i++) {
int to = v[x][i];
if (to == from) continue;
Dfs(to,x);
}
Insert(1,1,3*n,++dfs_clock,1);
}
void Modify(int o,int l,int r,int posi,int typ)
{
if (l == r) {
if (!typ) {
Dis[o] = -INF;
suf_plus[o] = suf_minus[o] = -INF;
pre_plus[o] = pre_minus[o] = -INF;
}
else {
Dis[o] = -INF;
suf_plus[o] = suf_minus[o] = 0;
pre_plus[o] = pre_minus[o] = 0;
}
return;
}
int mid = (l + r) >> 1;
if (posi <= mid) Modify(o<<1,l,mid,posi,typ);
else Modify(o<<1|1,mid+1,r,posi,typ);
maintain(o);
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int getcom()
{
char ch = getchar();
while (ch != 'G' && ch != 'C') ch = getchar();
return ch == 'G'?1:2;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint();
for (int i = 1; i < n; i++) {
int x = getint(),y = getint();
v[x].push_back(y);
v[y].push_back(x);
}
Dfs(n/2,0);
m = getint();
while (m--) {
int com = getcom();
if (com == 1) printf("%d\n",Dis[1]);
else {
int x = getint();
Modify(1,1,3*n,pos[x],Now[x]);
Now[x] ^= 1;
}
}
return 0;
}