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千题计划214:bzoj3589: 动态树

bzoj千题计划197:bzoj4247: 挂饰

bzoj千题计划118:bzoj1028: [JSOI2007]麻将

bzoj千题计划165:bzoj5127: 数据校验

bzoj千题计划144:bzoj1176: [Balkan2007]Mokia

bzoj千题计划177:bzoj1858: [Scoi2010]序列操作