bzoj2329: [HNOI2011]括号修复

传送门

觉得自底向上的splay贼神奇我竟然天真地写了自底向上,就不用kth了啊直接找到多好,然后发现我怕是个zz,我一reverse序号早乱了。。。

所以不能自底向上,至少我认为那是没有意义的。

然后就是取反的时候也是取异或,每次都会忘了这点。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=200010;
typedef long long LL;
using namespace std;
int rt,n,m,tot;
char s[N],o[10];

template<typename T>void read(T &x)  {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

int p[N],ch[N][2],v[N],flip[N],op[N],cover[N],sum[N],lmi[N],lmx[N],rmx[N],rmi[N],sz[N];
#define lc ch[x][0]
#define rc ch[x][1]
void update(int x) {
    sum[x]=sum[lc]+sum[rc]+v[x];
    sz[x]=sz[lc]+sz[rc]+1;
    lmi[x]=min(lmi[lc],sum[lc]+v[x]+lmi[rc]);
    lmx[x]=max(lmx[lc],sum[lc]+v[x]+lmx[rc]);
    rmi[x]=min(rmi[rc],sum[rc]+v[x]+rmi[lc]);
    rmx[x]=max(rmx[rc],sum[rc]+v[x]+rmx[lc]); 
}

void cover_it(int x,int w) {
    sum[x]=sz[x]*w; v[x]=w; 
    cover[x]=w; flip[x]=op[x]=0; 
    lmi[x]=rmi[x]=min(0,sz[x]*w); 
    lmx[x]=rmx[x]=max(0,sz[x]*w);
}

void get_oppo(int x) {
    swap(lmi[x],lmx[x]); 
    swap(rmi[x],rmx[x]);
    if(cover[x]) cover[x]*=-1; else op[x]^=1; //取反也是异或! 
    sum[x]*=-1,v[x]*=-1;
    lmi[x]*=-1,lmx[x]*=-1;
    rmi[x]*=-1,rmx[x]*=-1;
}

void reverse(int x) {
    swap(lc,rc);
    swap(lmi[x],rmi[x]);
    swap(lmx[x],rmx[x]);
    flip[x]^=1;
}

void down(int x) {
    if(!cover[x]&&!op[x]&&!flip[x]) return;
    if(cover[x]) {
        if(lc) cover_it(lc,cover[x]);
        if(rc) cover_it(rc,cover[x]); 
    }
    if(op[x]) {
        if(lc) get_oppo(lc);
        if(rc) get_oppo(rc);
    }
    if(flip[x]) {
        if(lc) reverse(lc);
        if(rc) reverse(rc);
    }
    cover[x]=op[x]=flip[x]=0; 
}

void rotate(int x) {
    int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
    if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
    ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
    ch[x][r]=y; p[y]=x;
    update(y); update(x);
}

void splay(int x,int FA) {
    /*static int g[N],top=0,tp;
    for(tp=x;tp!=FA;tp=p[tp]) g[++top]=tp;
    g[++top]=tp;
    while(top) down(g[top--]);*/ //不能自底向上! 
    for(;p[x]!=FA;rotate(x)) {
        int y=p[x],z=p[y];
        if(z!=FA) ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y); 
    }
    if(!FA) rt=x; 
}

int build(int sz) {
    if(!sz) return 0;
    int ls,rs,x;
    ls=build(sz>>1);
    x=++tot;
    rs=build(sz-(sz>>1)-1);
    if(ls) p[ls]=x; lc=ls; 
    if(rs) p[rs]=x; rc=rs;
    update(x);
    return x;
}

int kth(int k) {
    for(int x=rt;x;) {
        down(x);
        if(sz[lc]+1==k) return x;
        if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc;
        else x=lc;
    } return -1;
}

int get_it(int l,int r) {
    l=kth(l); r=kth(r+2);
    splay(l,0); splay(r,l);
    return ch[r][0];
}

int main() {
#ifdef DEBUG
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
    read(n); read(m);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++) v[i+1]=(s[i]=='(')?-1:1;
    /*ch[n+1][1]=n+2; p[n+2]=n+1;
    ch[n+2][0]=build(n); p[ch[n+2][0]]=n+2;
    update(n+2); update(n+1); rt=n+1;*/
    rt=build(n+2);
    while(m--) {
        scanf("%s",o);
        int l,r,w;
        read(l); read(r);
        int x=get_it(l,r);
        if(o[0]=='R') {
            scanf("%s",o);
            w=(o[0]=='(')?-1:1;
            cover_it(x,w); 
        }
        else if(o[0]=='S') reverse(x);
        else if(o[0]=='I') get_oppo(x);
        else if(o[0]=='Q') {
            int ans=(lmx[x]+1)/2+(-rmi[x]+1)/2; //// no lmi rmx
            printf("%d\n",ans);
        }
        update(p[x]); update(p[p[x]]); 
    }
    return 0;
}
/*
4 4
((((
Replace 1 2 )
Swap 2 3
Invert 3 4
Query 1 4 

4 3
((((
Swap 2 4 
Swap 3 4 
Query 1 4 
*/
View Code

 

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
#define ll long long
#define db double
int n=40,m=50;

char cc; ll ff;
template<typename T>void read(T& aa) {
    aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main() {
    srand((unsigned)time(NULL));
    printf("%d %d\n",n,m);
    for(int i=1;i<=n;i++) {
        int o=rand()%2;
        if(o==1) printf("(");
        else printf(")");
    } puts("");
    for(int i=1;i<=m;i++) {
        int o=rand()%4;
        int l=rand()%n+1,r=rand()%n+1;
        if(l>r) swap(l,r);
        if(o==1) {
            printf("Replace "); 
            printf("%d %d ",l,r);
            o=rand()%2;
            if(o==1) printf("(");
            else printf(")");
        }
        else if(o==2) {
            printf("Query "); 
            printf("%d %d ",l,r);
        }
        else if(o==3) {
            printf("Swap "); 
            printf("%d %d ",l,r);
        }
        else {
            printf("Invert "); 
            printf("%d %d ",l,r);
        }
        puts("");
    }
    return 0;
}
rand

 

posted @ 2018-03-10 10:10  啊宸  阅读(196)  评论(0编辑  收藏  举报