poj3580 or bzoj1895(splay)

參考:Clove_unique鍵盤裏的青春

支持某位置單點插入,區間加法,區間最小值,單點刪除,區間翻轉,區間輪轉。
甚至還可以再加上區間賦蓋,區間和,區間最大子段和等一系列線段樹可進行的操作。
splay打包帶走

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int maxn=2e5+7;
const int inf=1e9;

int tot,rt;
void init(){tot=rt=0;}

int siz[maxn],val[maxn],rev[maxn],add[maxn],minn[maxn],ch[maxn][2],f[maxn],W[maxn];

bool which(int x){ return ch[f[x]][1]==x; }

void connect(int s,int fa,int lr){
    ch[fa][lr]=s;
    f[s]=fa;
}

void pushup(int k){
    if(k){
        minn[k]=val[k];
        siz[k]=1;
        if(ch[k][0]) siz[k]+=siz[ch[k][0]],minn[k]=min(minn[k],minn[ch[k][0]]);
        if(ch[k][1]) siz[k]+=siz[ch[k][1]],minn[k]=min(minn[k],minn[ch[k][1]]);
    }
}

void pushdown(int k){
    if(!k) return ;
    if(rev[k]){
        if(ch[k][0]) rev[ch[k][0]]^=1;
        if(ch[k][1]) rev[ch[k][1]]^=1;
        swap(ch[k][0],ch[k][1]);
        rev[k]=0;
    }
    if(add[k]){
        if(ch[k][0]) val[ch[k][0]]+=add[k],minn[ch[k][0]]+=add[k],add[ch[k][0]]+=add[k];
        if(ch[k][1]) val[ch[k][1]]+=add[k],minn[ch[k][1]]+=add[k],add[ch[k][1]]+=add[k];
        add[k]=0;
    }
}
queue<int> q;
int newnode(int w){
    int k;
    if(q.size()) { k=q.front(); q.pop(); }
    else k=++tot;
    rev[k]=add[k]=f[k]=ch[k][0]=ch[k][1]=0;
    minn[k]=val[k]=w;
    siz[k]=1;
    return k;
}

void clear(int k){
    rev[k]=add[k]=f[k]=ch[k][0]=ch[k][1]=minn[k]=val[k]=0;
    q.push(k);
}

int build(int l,int r,int fa){
    if(l>r) return 0;
    int mid=l+r>>1;
    int now=newnode(W[mid]);
    f[now]=fa;
    ch[now][0]=build(l,mid-1,now);
    ch[now][1]=build(mid+1,r,now);
    pushup(now);
    return now;
}

void rotate(int x){
    pushdown(f[x]),pushdown(x);
    int old=f[x],oldf=f[old],who=which(x);
    connect(ch[x][who^1],old,who);
    if(oldf) connect(x,oldf,which(old));
    f[x]=oldf;
    connect(old,x,who^1);
    pushup(old),pushup(x);
}

//將x轉到pos的兒子處;
void splay(int x,int pos){
    for(int fa;(fa=f[x])!=pos;rotate(x))
        if(f[fa]!=pos) rotate(which(fa)==which(x)?fa:x);
    if(!pos) rt=x;
}

int kth(int x){
    int now=rt;
    while(1){
        pushdown(now);
        if(ch[now][0]&&x<=siz[ch[now][0]]) now=ch[now][0];
        else{
            x-=siz[ch[now][0]];
            if(x==1) return now;
            --x;
            now=ch[now][1];
        }

    }
    return -1;
}

pair<int,int> splayLR(int l,int r){
    int L=kth(l);
    int R=kth(r);
    splay(L,0);
    splay(R,L);
    return make_pair(L,R);
}
void add_to_some(int l,int r,int x){
    if(l>r) swap(l,r);
    pair<int,int> P=splayLR(l-1,r+1);
    int L=P.first,R=P.second;
    add[ch[R][0]]+=x;
    minn[ch[R][0]]+=x;
    val[ch[R][0]]+=x;
    pushup(R),pushup(rt);
}

void reverse(int l,int r){
    if(l>r) swap(l,r);
    pair<int,int> P=splayLR(l-1,r+1);
    int L=P.first,R=P.second;
    rev[ch[R][0]]^=1;
}

void insert(int pos,int x){
    pair<int,int> P=splayLR(pos,pos+1);
    int L=P.first,R=P.second;
    int now=newnode(x);
    connect(now,R,0);
    pushdown(R),pushup(rt);
}

void del(int pos){
    pair<int,int> P=splayLR(pos-1,pos+1);
    int L=P.first,R=P.second;
    clear(ch[R][0]);
    ch[R][0]=0;
    pushup(R),pushup(rt);
}

int askMin(int l,int r){
    if(l>r) swap(l,r);
    pair<int,int> P=splayLR(l-1,r+1);
    return minn[ch[P.second][0]];
}

void init(int n){
    init();
    W[1]=-inf;
    W[n+2]=inf;
    for(int i=2;i<=n+1;++i) scanf("%d",&W[i]);
    rt=build(1,n+2,0);
}

void exchange(int l,int r,int x){
    if(l>r) swap(l,r);
    x%=(r-l+1);
    if(!x) return ;
    int l1=l,r1=r-x,l2=r-x+1,r2=r;
    pair<int,int> pos2=splayLR(l2-1,r2+1);
    int L=pos2.first,R=pos2.second;
    int temp_r=ch[R][0]; ch[R][0]=0;
    pushup(R),pushup(rt);
    pair<int,int> pos1=splayLR(l1-1,l1);
    R=pos1.second;
    ch[R][0]=temp_r;
    f[temp_r]=R;
    pushup(R),pushup(rt);
}
char s[9];
/*
    A 區間加法
    D 刪除下標爲x的數
    M 區間最小值
    E 區間翻轉
    else 區間輪換x次;
*/
int main(){
    int n,q,l,r,x;
    scanf("%d",&n);
    init(n);
    scanf("%d",&q);
    while(q--){
        scanf("%s",s);
        if(s[0]=='A'){ scanf("%d%d%d",&l,&r,&x); add_to_some(++l,++r,x); }
        else if(s[0]=='I'){ scanf("%d%d",&l,&x); insert(++l,x); }
        else if(s[0]=='D'){ scanf("%d",&x); del(++x); }
        else if(s[0]=='M'){ scanf("%d%d",&l,&r); printf("%d\n",askMin(++l,++r)); }
        else if(s[3]=='E'){ scanf("%d%d",&l,&r); reverse(++l,++r); }
        else{ scanf("%d%d%d",&l,&r,&x); exchange(++l,++r,x); }
    }

    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章