• BZOJ 1095 捉迷藏(线段树维护括号序列)


    对于树的一个括号序列,树上两点的距离就是在括号序列中两点之间的括号匹配完之后的括号数。。。

    由此可以得出线段树的做法。。

    #include<cstdio>
    #include<iostream>
    #define maxn 100000
    #define inf (1<<25)
    using namespace std;
    int vis[maxn+10];
    struct node{
        int l1,l2,r1,r2,c1,c2,dis;
        void val(int x){
            c1=c2=0;
            l1=l2=r1=r2=dis=-inf;
            if(x==-1)c2=1;
            else if(x==-2)c1=1;
            else if(vis[x]==1)l1=l2=r1=r2=0;
        }
        void merge(node &a,node &b){
            c1=a.c1+max(0,b.c1-a.c2);
            c2=b.c2+max(0,a.c2-b.c1);
            dis=max(max(a.dis,b.dis),max(a.r1+b.l2,a.r2+b.l1));
            l1=max(a.l1,max(b.l1-a.c2+a.c1,b.l2+a.c2+a.c1));
            l2=max(a.l2,b.l2+a.c2-a.c1);
            r1=max(b.r1,max(a.r1-b.c1+b.c2,a.r2+b.c1+b.c2));
            r2=max(b.r2,a.r2+b.c1-b.c2);
        }
    }s[maxn*3<<2];
    int num[maxn*3+10],tot;
    void update(int o,int l,int r,int p){
        if(l==r)s[o].val(num[p]);
        else{
            int m=l+r>>1;
            if(p<=m)update(o<<1,l,m,p);
            else update(o<<1|1,m+1,r,p);
            s[o].merge(s[o<<1],s[o<<1|1]);
        }
    }
    void build(int o,int l,int r){
        if(l==r)s[o].val(num[l]);
        else{
            int m=l+r>>1;
            build(o<<1,l,m);
            build(o<<1|1,m+1,r);
            s[o].merge(s[o<<1],s[o<<1|1]);
        }
    }
    struct EDGE{
        int u,v,next;
    }edge[2*maxn+10];
    int head[maxn+10],pp;
    void adde(int u,int v){
        edge[++pp]=(EDGE){u,v,head[u]};
        head[u]=pp;
    }
    int pos[maxn+10];
    void dfs(int u,int fa){
        num[++tot]=-1;
        pos[num[++tot]=u]=tot;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].v;
            if(v!=fa)dfs(v,u);
        }
        num[++tot]=-2;
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)vis[i]=1;
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }
        dfs(1,0);
        build(1,1,tot);
        int q,cnt=n;
        scanf("%d",&q);
        char e[2];
        while(q--){
            scanf("%s",e);
            if(e[0]=='G'){
                if(cnt==0)puts("-1");
                else if(cnt==1)puts("0");
                else printf("%d
    ",s[1].dis);
            }else{
                int u;
                scanf("%d",&u);
                cnt+=vis[u]=-vis[u];
                update(1,1,tot,pos[u]);
            }
        }   
        return 0;
    }
    View Code
  • 相关阅读:
    Js内存泄漏的几种情况
    简单工厂模式
    单例模式
    设计模式简介
    百度地图api-动态添加覆盖物
    ArcGIS发布地图服务后直接调用查看方法
    NetCDF 共享软件 中文
    Oracle服务器重命名
    NETCDF入门
    Oracle11gExpress和PL/SQL Developer安装
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6525210.html
Copyright © 2020-2023  润新知