hdu3487-splay模版题

通过分裂、合并来提供区间的旋转、插入操作。

可以在区间[1,n]的首尾加上虚拟节点防止RE。做各种需要用到儿子的操作前都先pushdown。

旋转时,gf->f->s,如果成一条直线,则先旋转gf,再转f;反之,先转f,再转gf。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(x,y,z) for (int x=y; x<=z; x++)
#define downrep(x,y,z) for (int x=y; x>=z; x--)
#define ms(x,y,z) memset(x,y,sizeof(z))
#define LL long long
#define repedge(x,y) for (int x=hed[y]; ~x; x=edge[x].nex)
inline int read(){
    int x=0; int w=0; char ch=0;
    while (ch<'0' || ch>'9') w|=ch=='-',ch=getchar();
    while (ch>='0' && ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return w? -x:x;
}
const int maxn=300005;
int n,m,cnt,sz[maxn],num[maxn],val[maxn],lazy[maxn],ch[maxn][3],root;
char s[15];
void newnode(int x,int v){
    lazy[x]=0; val[x]=v; sz[x]=num[x]=1; 
}
void pushup(int o){
    sz[o]=num[o]+sz[ch[o][0]]+sz[ch[o][1]];
}
void pushdown(int o){
    if (!lazy[o]) return; 
    swap(ch[o][0],ch[o][1]); lazy[ch[o][0]]^=1; lazy[ch[o][1]]^=1; lazy[o]=0;
}
int build(int l,int r){
    if (l>r) return 0; int x=++cnt; int mid=((l+r)>>1); newnode(x,mid);
    ch[x][0]=build(l,mid-1); ch[x][1]=build(mid+1,r); pushup(x); return x;
}
void rotate(int &o,int d){
    pushdown(o); int k=ch[o][d^1]; pushdown(k); ch[o][d^1]=ch[k][d]; ch[k][d]=o;
    pushup(o); pushup(k); o=k;

int cmp(int o,int &v){
    pushdown(o);
    if (v<=sz[ch[o][0]]) return 0;
    if (v<=sz[ch[o][0]]+num[o]) return -1;
    v-=sz[ch[o][0]]+num[o]; return 1;
}
void splay(int &o,int v){
    int d=cmp(o,v); if (d==-1) return; 
    int p=ch[o][d]; int d2=cmp(p,v);
    if (d2!=-1){ splay(ch[p][d2],v); if (d2==d) rotate(o,d^1); else rotate(ch[o][d],d2^1); }
    rotate(o,d^1);
}
void split(int o,int v,int &left,int &right){
    splay(o,v); right=ch[o][1]; ch[o][1]=0; pushup(o); left=o;
}
int merge(int left,int right){
    splay(left,sz[left]); ch[left][1]=right; pushup(left); return left;
}
void flip(int l,int r){
    int left,mid,right; split(root,l,left,mid); split(mid,r-l+1,mid,right);
    lazy[mid]^=1; root=merge(merge(left,mid),right);
}
void cut(int l,int r,int c){
    int left,mid,right; split(root,l,left,mid); split(mid,r-l+1,mid,right);
    root=merge(left,right); split(root,c+1,left,right); root=merge(merge(left,mid),right);
}
int tot;
void write(int o){
    if (!o) return;
    pushdown(o); 
    write(ch[o][0]);
    if ((1<=val[o])&&(val[o]<=n)) {
        ++tot; if (tot==n) printf("%d\n",val[o]); else printf("%d ",val[o]);
    } 
    write(ch[o][1]);
}
void enter(){ putchar('\n'); }
int main(){
    for ( ; ; ){
        scanf("%d%d",&n,&m);
        if ((n==-1)&&(m==-1)) break;
        cnt=0; root=build(0,n+1);
        rep(i,1,m) {
            scanf("%s",&s); 
            if (s[0]=='F'){ int l,r; scanf("%d%d",&l,&r); flip(l,r); }
            if (s[0]=='C'){ int a,b,c; scanf("%d%d%d",&a,&b,&c); cut(a,b,c); }
        }
        tot=0; write(root); 
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/shiveringkonnyaku/article/details/82657140
今日推荐