http://www.zybbs.org/JudgeOnline/problem.php?id=1095
囧……搞了两天……
本来一看题可以用树链剖分搞,无奈我还不会……然后想起神犇杨弋的《线段树》有这道题,于是乎膜拜了一下,发现这是最后留下的思考题= =!
然后又发现cqx神牛的论文中有讲解,于是乎又膜拜了一下……(不是一下,是一天……)
原理是很好理解的,用类似括号序列的方法,这样两个黑点间的距离就是未匹配括号的个数了,可以线性维护……但是写起来一个句子长得都越屏了,实在难调,做了一个小地方,要盯着屏幕找好久……(*_*)
经过一天半的努力和QZ神牛的论文注释,终于AC了……
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define MM 200001
#define MN 200001
#define INF 1000000
#define head -1
#define tail -2
#define lch x<<1
#define rch (x<<1)+1
using namespace std;
int color[MN],pos[MN],Sequence[MN*3],n,m,a,b,cnt,Dark;
bool vis[MN];
char s[10];
struct EDGE{
int pnt;
EDGE *pre;
EDGE (){}
EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){}
}Edge[MM*2],*SP=Edge,*edge[MM];
struct SegmentTree{
int left,right,dist;
int left_plus,right_plus,left_minus,right_minus;
}tree[MN*6];
inline void addedge(int a,int b){
edge[a]=new(++SP)EDGE(b,edge[a]);
edge[b]=new(++SP)EDGE(a,edge[b]);
}
void NewNode(int x,int p){
tree[x].left=(Sequence[p]==head);
tree[x].right=(Sequence[p]==tail);
tree[x].dist=-INF;
tree[x].left_plus=tree[x].right_plus=tree[x].left_minus=tree[x].right_minus=(Sequence[p]>=0 && color[Sequence[p]]==0)?0:-INF;
}
void update(int x){
tree[x].left=tree[rch].left+max(tree[lch].left-tree[rch].right,0);
tree[x].right=tree[lch].right+max(tree[rch].right-tree[lch].left,0);
tree[x].dist=max(max(tree[lch].dist,tree[rch].dist),max(tree[lch].right_plus+tree[rch].left_minus,tree[lch].right_minus+tree[rch].left_plus));
tree[x].left_plus=max(tree[lch].left_plus,max(tree[rch].left_plus+tree[lch].right-tree[lch].left,tree[rch].left_minus+tree[lch].right+tree[lch].left));
tree[x].left_minus=max(tree[lch].left_minus,tree[rch].left_minus-tree[lch].right+tree[lch].left);
tree[x].right_plus=max(tree[rch].right_plus,max(tree[lch].right_plus-tree[rch].right+tree[rch].left,tree[lch].right_minus+tree[rch].right+tree[rch].left));
tree[x].right_minus=max(tree[rch].right_minus,tree[lch].right_minus+tree[rch].right-tree[rch].left);
}
void build(int x,int l,int r){
if(l==r) NewNode(x,l);
else{
int mid=(l+r)>>1;
build(lch,l,mid);
build(rch,mid+1,r);
update(x);
}
}
void Modify(int x,int l,int r,int p){
if(l==r) NewNode(x,p);
else{
int mid=(l+r)>>1;
if(p<=mid) Modify(lch,l,mid,p);
else Modify(rch,mid+1,r,p);
update(x);
}
}
void dfs(int x){
vis[x]=true;
Sequence[++cnt]=head;
pos[x]=++cnt;
Sequence[cnt]=x;
for(EDGE *j=edge[x];j;j=j->pre)
if(!vis[j->pnt]) dfs(j->pnt);
Sequence[++cnt]=tail;
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
}
int Dark=n;
dfs(1);
build(1,1,cnt);
scanf("%d",&m);
while(m--){
scanf("%s",s);
if(s[0]=='G'){
if(Dark==0) printf("-1\n");
else if(Dark==1) printf("1\n");
else printf("%d\n",tree[1].dist);
}else{
scanf("%d\n",&a);
color[a]=!color[a];
if(color[a]) Dark--;
else Dark++;
Modify(1,1,cnt,pos[a]);
}
}
return 0;
}