可持久化Treap

/*

计算区间最小值,插入,删除,查找,区间每个都加一个数,旋转,翻转

可持久化Treap

*/ 
#include<iostream>
#include<stdio.h>
#include<algorithm>

using namespace std;

struct node{
    node *l,*r;
    int v,w,delta,size,rev,minx;
    void up(){
        minx=v;
        size=1;
        if(l){minx=min(minx,l->minx),size+=l->size;}
        if(r) {minx=min(minx,r->minx),size+=r->size;}
    }
    void down(){
        if(delta){
            if(l){l->delta+=delta;l->v+=delta;l->minx+=delta;}
            if(r){r->delta+=delta;r->v+=delta;r->minx+=delta;}
            delta=0;
        }
        if(rev){
            swap(l,r);
            if(l){l->rev^=1;}
            if(r){r->rev^=1;}
            rev=0;
        }
    }
}*root=NULL;

inline int sz(node* o){return o==NULL?0:o->size;}

void new_node(node* &o,int val){
    o=new node;
    o->l=o->r=NULL;
    o->w=rand();
    o->v=o->minx=val;
    o->size=1;
    o->delta=o->rev=0;
}

void insert(node* &o,int pos,int val){
    if(o==NULL) new_node(o,val);
    else{
        o->down();
        o->up();
        if(sz(o->l)>=pos){
            insert(o->l,pos,val);
            if(o->l->w > o->w){
                node* tmp=o;
                o=o->l;
                tmp->l=o->r;
                o->r=tmp;
                o->r->down();
                o->r->up();
            }
        }else{
            insert(o->r,pos-sz(o->l)-1,val);
            o->r->up();
            o->r->down();
            if(o->r->w > o->w){
                node *tmp=o;
                o=o->r;
                tmp->r=o->l;
                o->l=tmp;
                o->l->down();
                o->l->up();
            }
        }
        o->down();
        o->up();
    }
}

void cut(node* o,node* &p,node* &q,int num){
    if(num==0){
        p=NULL,q=o;
    }else if(sz(o)==num){
        p=o,q=NULL;
    }else{
        o->down();
        o->up();
        if(num<=sz(o->l)){
            q=o;
            cut(o->l,p,q->l,num);
            q->down();
            q->up();
        }else{
            p=o;
            cut(o->r,p->r,q,num-sz(o->l)-1);
            p->down();
            p->up();
        }
    }
}

void merge(node* &o,node* p,node* q){
    if(!p||!q){
        o=p?p:q;
    }else{
        p->down();
        p->up();
        q->down();
        q->up();
        if(p->w > q->w){
            o=p;
            merge(o->r,p->r,q);
        }else{
            o=q;
            merge(o->l,p,q->l);
        }
        o->down();
        o->up();
    }
}

void add(int l,int r,int val){
    node *a,*b,*c;
    cut(root,a,b,l-1);
    cut(b,b,c,r-l+1);
    b->v+=val;
    b->delta+=val;
    b->minx+=val;
    merge(a,a,b);
    merge(root,a,c);
}

void remove(int pos){
    node *a,*b,*c;
    cut(root,a,b,pos-1);
    cut(b,b,c,1);
    merge(root,a,c);
}

int query(int l,int r){
    node *a,*b,*c;
    cut(root,a,b,l-1);
    cut(b,b,c,r-l+1);
    int res=b->minx;
    merge(a,a,b);
    merge(root,a,c);
    return res;
}

void reverse(int l,int r){
    node *a,*b,*c;
    cut(root,a,b,l-1);
    cut(b,b,c,r-l+1);
    b->rev^=1;
    merge(a,a,b);
    merge(root,a,c);
}

void revolve(int l,int m,int r){
    node *a,*b,*c,*d;
    cut(root,a,b,l-1);
    cut(b,b,c,m-l+1);
    cut(c,c,d,r-m);
    merge(a,a,c);
    merge(a,a,b);
    merge(root,a,d);
}

int main(){
    int n,t,a,b,d;
    char s[10];
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&d);
        insert(root,i,d);
    }
    scanf("%d",&n);
    while(n--){
        scanf("%s", s);
        if(s[0] == 'A') {
            scanf("%d%d%d", &a, &b, &d);
            add(a,b,d);
        } else if(s[0] == 'I') {
            scanf("%d%d", &a, &d);
            insert(root,a,d);
        } else if(s[0] == 'D') {
            scanf("%d", &a);
            remove(a);
        } else if(s[0] == 'M') {
            scanf("%d%d", &a, &b);
            printf("%d\n", query(a,b));
        } else if(s[3] == 'E') {
            scanf("%d%d", &a, &b);
            reverse(a,b);
        } else {
            scanf("%d%d%d", &a, &b, &d);
            d = (d % (b-a+1) + (b-a+1)) % (b-a+1);
            if(d) revolve(a,b-d,b);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值