【ZJOI 2007】Hide 捉迷藏

  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;
}

  

  

posted @ 2011-08-01 17:06  Delostik  阅读(1142)  评论(0编辑  收藏  举报