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