洛谷【p2710】 數列 (splay)

一道複雜的二叉平衡樹,因爲有區間操作,所以用splay寫,注意細節。

題目傳送門

算是模板題吧

翻轉操作並不是將他暴力翻轉,只是開一個bool變量標記


(debug函數請忽略。。。。。。。)

#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#define ull unsigned long long
#define ll long long
#define inf 200009
#define INF 2147483647
using namespace std;
struct Splay{
    int val;//值 
    int siz,son[2],fa;//兒子大小 兒子節點 父節點 
    int maxsub,maxl,maxr,sumv;//最大子序列維護 左兒子最大序列 右兒子最大序列  和維護 (類似線段樹) 
    int p,set;//翻轉標記 makesame操作標記 
}t[inf];
int arr[inf];
int len,root;
queue <int> q;//循環使用被del的數組空間,防止mle 
void debug(){
    printf("\nDEBUG\n");
    for (int i=0;i<=len;i++){
        printf("%d: fa=%d son[0]=%d son[1]=%d l=%d r=%d max=%d sum=%d p=%d set=%d\n",i,t[i].fa,t[i].son[0],t[i].son[1],t[i].maxl,t[i].maxr,t[i].maxsub,t[i].sumv,t[i].p,t[i].set);
    } 
} 
void pushup(int u){//類似線段樹的pushup、pushdown 
    if (!u){
        return;
    }
    t[u].maxl=max(t[t[u].son[0]].maxl,t[t[u].son[0]].sumv+t[u].val+max(0,t[t[u].son[1]].maxl));
    t[u].maxr=max(t[t[u].son[1]].maxr,t[t[u].son[1]].sumv+t[u].val+max(0,t[t[u].son[0]].maxr));
    t[u].maxsub=max(t[u].val+max(0,t[t[u].son[0]].maxr)+max(0,t[t[u].son[1]].maxl),max(t[t[u].son[0]].maxsub,t[t[u].son[1]].maxsub));
    //最大子序列維護公式 
    t[u].sumv=t[t[u].son[0]].sumv+t[t[u].son[1]].sumv+t[u].val;
    t[u].siz=t[t[u].son[0]].siz+t[t[u].son[1]].siz+1;
    return;
}
void pushdown(int u){
    if (!u){
        return;
    }
    if (t[u].p){
        int revu=t[u].son[0];
        if (revu){
            swap(t[revu].son[0],t[revu].son[1]);
            swap(t[revu].maxl,t[revu].maxr);
            t[revu].p^=1;
        }
        revu=t[u].son[1];
        if (revu){
            swap(t[revu].son[0],t[revu].son[1]);
            swap(t[revu].maxl,t[revu].maxr);
            t[revu].p^=1;
        }
        t[u].p=0;
    }
    if (t[u].set!=-INF){
        int covu=t[u].son[0];
        if (covu){
            t[covu].set=t[covu].val=t[u].set;
            t[covu].sumv=t[covu].set*t[covu].siz;
            t[covu].maxl=t[covu].maxr=t[covu].maxsub=max(t[covu].set,t[covu].sumv);
        }
        covu=t[u].son[1];
        if (covu){
            t[covu].set=t[covu].val=t[u].set;
            t[covu].sumv=t[covu].set*t[covu].siz;
            t[covu].maxl=t[covu].maxr=t[covu].maxsub=max(t[covu].set,t[covu].sumv);
        }
        t[u].set=-INF;
    }
    return;
}
void rotate(int u,int p){//splay的旋轉,具體操作請看博客 
    int v=t[u].fa;
    t[v].son[!p]=t[u].son[p];
    t[t[v].son[!p]].fa=v;
    t[u].son[p]=v;
    t[u].fa=t[v].fa;
    t[t[v].fa].son[t[t[v].fa].son[1]==v]=u;
    t[v].fa=u;
    pushup(v);
    pushup(u);
    return;
}
void splay(int u,int to){
    while(t[u].fa!=to){
       // debug();
        if (t[t[u].fa].fa==to){
            rotate(u,t[t[u].fa].son[0]==u);
        }
        else{
            int f=t[u].fa,grandf=t[f].fa;
            int p=(t[grandf].son[0]==f);
            if (t[f].son[p]==u){
                rotate(u,!p);
                rotate(u,p);
            }
            else{
                rotate(f,p);
                rotate(u,p);
            }
        }
        pushup(u);
//        debug();
    }
    if (to==0){
        root=u;
    }
    return;
}
int newtree(int v){// 循環使用被del的數組空間,防止mle 
    int u;
    if (q.empty()){
        len++;
        u=len;
    }
    else{
        u=q.front();
        q.pop();
    }
    t[u].val=v;
    t[u].maxl=t[u].maxr=t[u].maxsub=-INF;
    t[u].p=0;
    t[u].set=-INF;
    return u;
}
int build(int l,int r){//建樹 
    if (l>r){
        return 0;
    }
    int mid=(l+r)/2,lson=0,rson=0;
    lson=build(l,mid-1);
    int u=newtree(arr[mid]);
    rson=build(mid+1,r);
    if (lson){
        t[u].son[0]=lson;
        t[lson].fa=u;
    }
    if (rson){
        t[u].son[1]=rson;
        t[rson].fa=u;
    }
    pushup(u);
//    debug();
    return u;
}
int getnum(int k){//找第k個數 
    int u=root;
    while(1){
        pushdown(u);
        if (k==t[t[u].son[0]].siz+1){
            break;
        }
        else if (k<=t[t[u].son[0]].siz){
            u=t[u].son[0];
        }
        else{
            k=k-t[t[u].son[0]].siz-1;
            u=t[u].son[1];
        }
    }
    return u;
}
void reverse(int l,int r){//旋轉操作 
    l=getnum(l);
    r=getnum(r+2);
    splay(l,0);
    splay(r,l);
    int revu=t[r].son[0];
    if (!revu){
        return;
    }
    swap(t[revu].son[0],t[revu].son[1]);
    swap(t[revu].maxl,t[revu].maxr);
    t[revu].p^=1;
    pushup(r);
    pushup(l);
    return;
}
void insert(int k,int l,int r){//插入操作 
    splay(getnum(k+2),0);
    splay(getnum(k+1),root);
    int u=build(l,r);
    t[t[root].son[0]].son[1]=u;
    t[u].fa=t[root].son[0];
    pushup(t[root].son[0]);
    pushup(root);
    return;
}
void del(int &u){ 
    if (!u){
        return;
    }
    q.push(u);
    t[u].fa=0;
    del(t[u].son[0]);
    del(t[u].son[1]);
    t[u].maxsub=t[u].maxl=t[u].maxr=-INF;
    u=0;
    return; 
}
void find_del(int l,int r){//刪除操作
    l=getnum(l);
    r=getnum(r+2);
    splay(l,0);
    splay(r,root);
    del(t[r].son[0]);
    pushup(r);
    pushup(l);
    return;
}
void setnum(int l,int r,int v){//makesame操作 
    l=getnum(l);
    r=getnum(r+2);
    splay(l,0);
    splay(r,l);
    int covu=t[r].son[0];
    if (!covu){
        return;
    }
    t[covu].set=t[covu].val=v;
    t[covu].sumv=v*t[covu].siz;
    t[covu].maxl=t[covu].maxr=t[covu].maxsub=max(v,t[covu].sumv);
    pushup(r);
    pushup(l);
    return;
}
int querymax(int l,int r){//兩個詢問操作 
    l=getnum(l);
    r=getnum(r+2);
    splay(l,0);
    splay(r,root);
    return t[t[r].son[0]].maxsub;
}
int querysum(int l,int r){
    l=getnum(l);
    r=getnum(r+2);
    splay(l,0);
    splay(r,root);
    return t[t[r].son[0]].sumv;
}
int main(){
    int n,m,x,y,z;
    char s[15];
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++){
        scanf("%d",&arr[i]);
    }
    arr[0]=arr[n+1]=0;
    t[0].maxl=t[0].maxr=t[0].maxsub=-INF;
    root=build(0,n+1);
//  debug();
    for (int i=0;i<m;i++){
        scanf("%s",&s);
        if (s[0]=='I'){
            scanf("%d%d",&x,&y);
            for (int i=1;i<=y;i++){
                scanf("%d",&arr[i]);
            }
            insert(x,1,y);
        }
        else if (s[0]=='D'){
            scanf("%d%d",&x,&y);
            find_del(x,x+y-1);
        }
        else if (s[0]=='M' && s[2]=='K'){
            scanf("%d%d%d",&x,&y,&z);
            setnum(x,x+y-1,z);
        }
        else if (s[0]=='R'){
            scanf("%d%d",&x,&y);
            reverse(x,x+y-1);
        }
        else if (s[0]=='G' && s[3]=='-'){
            scanf("%d%d",&x,&y);
            printf("%d\n",querysum(x,x+y-1));
        }
        else if (s[0]=='G'){
            scanf("%d",&x);
            printf("%d\n",t[getnum(x+1)].val);
        }
        else{
            scanf("%d%d",&x,&y);
            printf("%d\n",querymax(x,x+y-1));
        }
//      debug();
    }
}

 

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