bzoj2209: [Jsoi2011]括号序列

还是个splay模板,写了一个晚上…太菜了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    char ch=getchar();int f=0,x=1;
    while(ch<'0'||ch>'9'){if(ch=='-') x=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();}
    return f*x;
}
int n,m,fa[100005],c[100005][2],cnt,key[100005],rt;
bool rev[100005],neg[100005];
char s[100005];
int pos[100005],prex[100005],sufx[100005],pren[100005],sufn[100005];
int size[100005],sum[100005];
void update(int now)
{
    prex[0]=sufx[0]=-1000000000; 
    pren[0]=sufn[0]=1000000000; key[0]=0;
    //key[1]=0;
    int l=c[now][0],r=c[now][1];
    size[now]=size[l]+size[r]+1;
    sum[now]=sum[l]+sum[r]+key[now];
    int lenp=max(sum[l]+key[now],sum[l]+prex[r]+key[now]);
    prex[now]=max(lenp,prex[l]);
    lenp=min(sum[l]+key[now],sum[l]+pren[r]+key[now]);
    pren[now]=min(lenp,pren[l]);
    int lens=max(sum[r]+key[now],sum[r]+sufx[l]+key[now]);
    sufx[now]=max(lens,sufx[r]);
    lens=min(sum[r]+key[now],sum[r]+sufn[l]+key[now]);
    sufn[now]=min(lens,sufn[r]);
    //cout<<prex[now]<<" "<<pren[now]<<" "<<sufx[now]<<" "<<sufn[now]<<" "<<sum[now]<<endl;
}
void change(int now)
{
    swap(prex[now],sufx[now]);
    swap(pren[now],sufn[now]);
}
void change1(int now)
{
    sum[now]=-sum[now];
    key[now]=-key[now];
    prex[now]=-prex[now];sufx[now]=-sufx[now];
    pren[now]=-pren[now];sufn[now]=-sufn[now];
    swap(prex[now],pren[now]);
    swap(sufn[now],sufx[now]);
}
void pushdown(int x)
{
    if(rev[x])
    {
        change(c[x][0]);change(c[x][1]);
        swap(c[x][0],c[x][1]);
        rev[c[x][0]]^=1;rev[c[x][1]]^=1;
        rev[x]=0;
    }
    if(neg[x])
    {
        change1(c[x][0]);change1(c[x][1]);
        neg[c[x][0]]^=1;neg[c[x][1]]^=1;
        neg[x]=0;
    }
}
void rotate(int x,int &k)
{
    int y=fa[x],z=fa[y],l,r;
    //cout<<x<<" "<<y<<" "<<k<<endl;
    pushdown(y);pushdown(x);
    if(c[y][1]==x) l=1;else l=0;r=l^1;
    if(y==k) k=x;
    else
    {
        if(c[z][0]==y) c[z][0]=x;else c[z][1]=x;
    }
    fa[y]=x;fa[x]=z;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    update(y);update(x);
}
void splay(int x,int &k)
{
    while(x!=k)
    {
        //cout<<x<<" "<<k<<endl;
        int y=fa[x],z=fa[y];
        if(y!=k)
        {
            if(c[y][0]==x^c[z][0]==y) rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
int build(int l,int r,int p)
{
    if(l>r) return 0;
    int mid=l+r>>1;int now=++cnt;
    key[now]=pos[mid];fa[now]=p;
    c[now][0]=build(l,mid-1,now);
    c[now][1]=build(mid+1,r,now);
    update(now);
        //cout<<l<<" "<<r<<" "<<now<<"!"<<endl;
    //cout<<prex[now]<<" "<<pren[now]<<" "<<sufx[now]<<" "<<sufn[now]<<" "<<sum[now]<<endl;
    return now;
}
int find(int x)
{
    int now=rt;
    while(1)
    {
        pushdown(now);
        if(x<=size[c[now][0]])
        now=c[now][0];
        else
        {
            int ans=size[c[now][0]]+1;
            if(ans==x) return now;
            x-=ans;now=c[now][1];
        }
    }
}
int main()
{
    n=read();m=read();
    scanf("%s",s+1);

    for(int i=1;i<=n;i++)
    if(s[i]=='(') pos[i]=-1;else pos[i]=1;
    rt=build(0,n+1,0);
    //for(int j=1;j<=n+1;j++) cout<<prex[j]<<" "<<sufx[j]<<" "<<sufn[j]<<" "<<pren[j]<<endl;
    for(int i=1;i<=m;i++)
    {
        int op=read(),x=read(),y=read();
        int l=find(x),r=find(y+2);
        splay(l,rt);splay(r,c[l][1]);
        int t=c[c[rt][1]][0];//cout<<t<<endl;
        //for(int j=0;j<=n+1;j++) cout<<prex[j]<<" "<<sufx[j]<<" "<<sufn[j]<<" "<<pren[j]<<endl;
        if(op==0)
        {
            int ans=prex[t],ans1=sufn[t];
            if(ans1>0) ans1=0;
            else ans1=-ans1;
            if(ans<0) ans=0;
            //cout<<ans<<" "<<ans1<<endl;
            if(ans&1||ans1&1) printf("%d\n",(ans+ans1>>1)+1);
            else printf("%d\n",ans+ans1>>1);
        }
        if(op==1)
        {
            neg[t]^=1;
            change1(t);
            update(c[rt][1]);update(rt);
        }
        if(op==2)
        {
            rev[t]^=1;
            change(t);update(c[rt][1]);update(rt);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值