1095:[ZJOI 2007]Hide鬼ごっこ

2162 ワード

辛すぎて辛すぎて辛すぎて
鶏の線分の木の神題を炒めます
膜島娘OrzOrzOrz題解
#include<iostream>
#include<cstdio>
#include<cstring>
#define lc o<<1
#define rc o<<1|1
using namespace std;
const int inf=1e9;
struct Node{
	int l,r,a,b,rp,rm,lp,lm,dis;
}tr[1200005];
int tp[300005],black;								//0   1  2  
inline void pushup(int o){
	int a=tr[lc].a,b=tr[lc].b,c=tr[rc].a,d=tr[rc].b;
	if(b<c){
		tr[o].a=a+c-b;
		tr[o].b=d;
	}else{
		tr[o].a=a;
		tr[o].b=b+d-c;
	}
	tr[o].dis=max(max(tr[lc].dis,tr[rc].dis),max(tr[lc].rp+tr[rc].lm,tr[lc].rm+tr[rc].lp));
	tr[o].rp=max(tr[rc].rp,max(tr[lc].rp-c+d,tr[lc].rm+c+d));
	tr[o].rm=max(tr[lc].rm+c-d,tr[rc].rm);
	tr[o].lp=max(tr[lc].lp,max(tr[rc].lp-b+a,tr[rc].lm+a+b));
	tr[o].lm=max(tr[rc].lm+b-a,tr[lc].lm);
}
void build(int o,int l,int r){
	tr[o].l=l;tr[o].r=r;
	if(l==r){
		tr[o].dis=-inf;
		if(tp[l])tr[o].rp=tr[o].rm=tr[o].lp=tr[o].lm=-inf;
		if(tp[l]==1)tr[o].b=1;
		if(tp[l]==2)tr[o].a=1;
		return;
	}
	int m=l+r>>1;
	build(lc,l,m);build(rc,m+1,r);
	pushup(o);
}
void update(int o,int p){
	int l=tr[o].l,r=tr[o].r;
	if(l==r){
		if(!tr[o].lp){
			black--;
			tr[o].lp=tr[o].lm=tr[o].rp=tr[o].rm=-inf;
		}else{
			black++;
			tr[o].lp=tr[o].lm=tr[o].rp=tr[o].rm=0;
		}
	}else{
		int m=l+r>>1;
		if(p<=m)update(lc,p);
		else update(rc,p);
		pushup(o);
	}
}
struct Edge{int to,next;}e[200005];
int head[100005],cnt,pos[100005],sz;
void ins(int u,int v){
	cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
}
void dfs(int u,int fa){
	tp[++sz]=1;pos[u]=++sz;
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].to;
		if(v==fa)continue;
		dfs(v,u);
	}
	tp[++sz]=2;
}
int main(){
	int n;scanf("%d",&n);
	int u,v;
	for(int i=1;i<n;i++){
		scanf("%d%d",&u,&v);
		ins(u,v);ins(v,u);
	}
	dfs(1,0);build(1,1,3*n);
	int q;scanf("%d",&q);
	char opt[10]; 
	black=n;
	while(q--){
		scanf("%s",opt);
		if(opt[0]=='C'){
			scanf("%d",&u);
			update(1,pos[u]);
		}else{
			if(black==0)puts("-1");
			else if(black==1)puts("0");
			else printf("%d
",tr[1].dis); } } return 0; }