【BZOJ 1095】 [ZJOI2007]Hide 捉迷藏 括号序列

太神了!!!!
这种方法看来不适合我这种蒟蒻!!
下午还是老老实实用分治把!!

#include <cstdio>
#include <iostream>
#include <algorithm>
#define INF 1000000000
using namespace std;
struct H
{
    int ans;
    int C2,C5;
    int L25,R25;
    int L5,R2;
}seg_num[1000000*4+1];
int init[1000000+1];
int n,m;
int tot,g[1000000+1],num[1000000+1],nnext[1000000+1];

int pos[1000000+1];
bool is_black[1000000+1];
int v[1000000*3+1],cnt;

void Add(int x,int y)
{
    tot++;
    nnext[tot]=g[x];
    g[x]=tot;
    num[tot]=y;
}

void dfs (int x)
{
    v[++cnt]=-5;
    v[++cnt]=x;pos[x]=cnt;
    for(int i=g[x];i;i=nnext[i])
        if(!is_black[num[i]])
            is_black[num[i]]=true,dfs(num[i]);
    v[++cnt]=-2;
}
void Up(int now)
{
    int L=now*2,R=now*2+1;
    if(seg_num[L].C5>seg_num[R].C2)
    {
        seg_num[now].C2=seg_num[L].C2;
        seg_num[now].C5=seg_num[L].C5-seg_num[R].C2+seg_num[R].C5;
    }
    else
    {
        seg_num[now].C2=seg_num[L].C2+seg_num[R].C2-seg_num[L].C5;
        seg_num[now].C5=seg_num[R].C5;
    }
    seg_num[now].ans=max(max(seg_num[L].ans,seg_num[R].ans),max(seg_num[L].R25+seg_num[R].L5,seg_num[R].L25+seg_num[L].R2));
    seg_num[now].L25=max(seg_num[L].L25,max(seg_num[L].C5+seg_num[L].C2+seg_num[R].L5,seg_num[L].C2-seg_num[L].C5+seg_num[R].L25));
    seg_num[now].R25=max(seg_num[R].R25,max(seg_num[L].R2+seg_num[R].C2+seg_num[R].C5,seg_num[L].R25+seg_num[R].C5-seg_num[R].C2));
    seg_num[now].L5=max(seg_num[L].L5,seg_num[R].L5+seg_num[L].C5-seg_num[L].C2);
    seg_num[now].R2=max(seg_num[R].R2,seg_num[L].R2+seg_num[R].C2-seg_num[R].C5);
}
void Build(int now,int L,int R)
{
    if(L==R)
    {
        if(v[L]<0)
        {
            seg_num[now].L25=seg_num[now].R25=seg_num[now].R2=seg_num[now].L5=-INF;
            if(v[L]==-2)
                seg_num[now].C2=1;
            else
                seg_num[now].C5=1;
        }
        
        return ;
    }
    int mid=(L+R)/2;
    Build(now*2,L,mid);
    Build(now*2+1,mid+1,R);
    Up(now);
}
void Change(int now,int L,int R,int loc)
{
    if(L==R)
    {
        if(is_black[v[L]]==1)
            seg_num[now]=(H){0,0,0,0,0,0,0};
        else
            seg_num[now]=(H){0,0,0,-INF,-INF,-INF,-INF};
        return ;
    }
    int mid=(L+R)/2;
    if(loc<=mid)
    Change(now*2,L,mid,loc);
    else
    Change(now*2+1,mid+1,R,loc);
    Up(now);
}
int main()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        Add(x,y);
        Add(y,x);
    }
    is_black[1]=true;
    dfs(1);
    n*=3;
    Build(1,1,n); 
    cin>>m; 
    char c;int x;
    int nn=n/3;
    while(m--)
    {
        getchar();
        c=getchar();
        if(c=='G')
        {
            if(nn==0) printf("-1\n");
            else if(nn==1) printf("0\n");
            else printf("%d\n",seg_num[1].ans);
        }
        else
        {
            scanf("%d",&x);
            if(is_black[x]==true)
                nn--;
            else nn++;
            is_black[x]=!is_black[x];
            Change(1,1,n,pos[x]);
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/ofsxb/p/5138654.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值