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

}

  

  

你可能感兴趣的:(2007)