bzoj千题计划252:bzoj1095: [ZJOI2007]Hide 捉迷藏

时间:2023-03-09 05:20:39
bzoj千题计划252:bzoj1095: [ZJOI2007]Hide 捉迷藏

http://www.lydsy.com/JudgeOnline/problem.php?id=1095

点分树+堆 请去看 http://www.cnblogs.com/TheRoadToTheGold/p/8463436.html

线段树维护括号序列

对树进行dfs,入栈时加一个左括号,出栈时加一个右括号,那么书上两点间的距离=括号序列两点间不匹配括号数

例:

树1--2--3,2为根

括号序列为 (2(3)(1))

2和1的距离 为 ()( = 1, 3和1的距离为 )( =2

具体怎么维护不想写了,去看曹钦翔的冬令营讲稿《数据结构的提炼与压缩》(p29、30)吧

#include<cstdio>
#include<iostream> #define N 100001 using namespace std; int front[N],nxt[N<<],to[N<<],tot; int id[N];
int num[N*]; bool light[N]; #define max(a,b) ((a)>(b) ? (a) : (b)) struct node
{
int a,b,dis;
int right_plus,right_minus,left_plus,left_minus; void get_val(int x)
{
a=b=;
right_plus=right_minus=left_plus=left_minus=dis=-1e7;
if(num[x]==-) b=;
else if(num[x]==-) a=;
else if(!light[num[x]]) right_plus=right_minus=left_plus=left_minus=dis=;
} node operator + (node p)
{
node k;
k.a=max(a,a+p.a-b);
k.b=max(p.b,p.b+b-p.a);
k.dis=max(max(dis,p.dis),max(right_plus+p.left_minus,right_minus+p.left_plus));
int A=a,B=b,C=p.a,D=p.b;
k.right_plus=max(p.right_plus,max(right_plus+D-C,right_minus+D+C));
k.right_minus=max(p.right_minus,right_minus+C-D);
k.left_plus=max(left_plus,max(A+B+p.left_minus,A-B+p.left_plus));
k.left_minus=max(left_minus,B-A+p.left_minus);
return k;
} }tr[N*<<]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void dfs(int x,int fa)
{
num[++tot]=-;
id[num[++tot]=x]=tot;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa) dfs(to[i],x);
num[++tot]=-;
} void build(int k,int l,int r)
{
if(l==r)
{
tr[k].get_val(l);
return;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
tr[k]=tr[k<<]+tr[k<<|];
} void change(int k,int l,int r,int pos)
{
if(l==r)
{
tr[k].get_val(l);
return;
}
int mid=l+r>>;
if(pos<=mid) change(k<<,l,mid,pos);
else change(k<<|,mid+,r,pos);
tr[k]=tr[k<<]+tr[k<<|];
} int main()
{
int n,u,v;
read(n);
for(int i=;i<n;++i)
{
read(u); read(v);
add(u,v);
}
tot=;
dfs(,);
build(,,tot);
int m; char s[];
read(m);
int cnt=n;
while(m--)
{
scanf("%s",s);
if(s[]=='G')
{
if(cnt<=) printf("%d\n",cnt-);
else printf("%d\n",tr[].dis);
}
else
{
read(u);
if(light[u]) cnt++;
else cnt--;
light[u]^=;
change(,,tot,id[u]);
}
}
return ;
}