bzoj千题计划252:bzoj1095: [ZJOI2007]Hide 捉迷藏
Posted 日拱一卒 功不唐捐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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<<1],to[N<<1],tot; int id[N]; int num[N*3]; 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=0; right_plus=right_minus=left_plus=left_minus=dis=-1e7; if(num[x]==-1) b=1; else if(num[x]==-2) a=1; else if(!light[num[x]]) right_plus=right_minus=left_plus=left_minus=dis=0; } 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*3<<2]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-\'0\'; 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]=-1; id[num[++tot]=x]=tot; for(int i=front[x];i;i=nxt[i]) if(to[i]!=fa) dfs(to[i],x); num[++tot]=-2; } void build(int k,int l,int r) { if(l==r) { tr[k].get_val(l); return; } int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); tr[k]=tr[k<<1]+tr[k<<1|1]; } void change(int k,int l,int r,int pos) { if(l==r) { tr[k].get_val(l); return; } int mid=l+r>>1; if(pos<=mid) change(k<<1,l,mid,pos); else change(k<<1|1,mid+1,r,pos); tr[k]=tr[k<<1]+tr[k<<1|1]; } int main() { int n,u,v; read(n); for(int i=1;i<n;++i) { read(u); read(v); add(u,v); } tot=0; dfs(1,0); build(1,1,tot); int m; char s[3]; read(m); int cnt=n; while(m--) { scanf("%s",s); if(s[0]==\'G\') { if(cnt<=1) printf("%d\\n",cnt-1); else printf("%d\\n",tr[1].dis); } else { read(u); if(light[u]) cnt++; else cnt--; light[u]^=1; change(1,1,tot,id[u]); } } return 0; }
以上是关于bzoj千题计划252:bzoj1095: [ZJOI2007]Hide 捉迷藏的主要内容,如果未能解决你的问题,请参考以下文章
bzoj千题计划118:bzoj1028: [JSOI2007]麻将