无旋Treap

无旋treap的核心操作时分裂与合并,分裂分为按值分裂和按排名分裂,按值分裂用于维护权值平衡树,按排名分裂用于维护序列。

按值分裂平衡树。

struct Treap{
	struct tree{
        int l,r,v,p/*随机值*/,w;
	}t[N];
	int tot,root,INF=0x7fffffff,s[N];
    #define l(p) (t[p].l)
    #define r(p) (t[p].r)
    #define p(x) (t[x].p)
    #define w(p) (t[p].w)
    #define v(p) (t[p].v)
	inline int rand(){
        static default_random_engine x;
        static uniform_int_distribution<int>f(-1e8,1e8);
        return f(x);
	}
	inline int create(int v){
        int p=s[0]?s[s[0]--]:++tot;
        t[p]={0,0,v,rand(),1};
		return p;
	}
    inline void recycle(int p){
        t[s[++s[0]]=p];
    }
	inline void pushup(int p){
        w(p)=w(l(p))+w(r(p))+1;/*size包括自己*/
	}
	void split(int p,int&x,int&y,int v){/*将p分裂成x,y两颗子树,满足v(x)<=v,v(y)>v*/
		if(!p)return x=y=0,void();/*分到底*/
		if(v(p)<=v)x=p/*确定左子树的根*/,split(/*向右子树分裂*/r(p),r(p),y,v);
		else y=p/*确定右子树的根*/,split(/*向左子树分裂*/l(p),x,l(p),v);
		pushup(p);
	}
	void merge(int&p,int x,int y){/*将x,y合并为p一颗子树,由于保证了v(x)<v(y),所以每棵树按照随机值合并保证深度,满足随机值小根堆*/
		if(!x||!y)return p=x|y,void();/*叶子节点*/
		if(p(x)<=p(y))p=x/*左子树为父节点*/,merge(r(p),r(p),y);/*合并左子树有半部分和右子树*/
		else p=y/*右子树为父节点*/,merge(l(p),x,l(p));/*合并左子树和右子树左半部分*/
		pushup(p);
	}
	inline int kth(int p,int x){
		while(w(l(p))+1!=x){/*x不为此区间的根*/
			if(x<=w(l(p)))p=l(p);
			else x-=w(l(p))+1/*减去左子树的节点数*/,p=r(p);
		}
		return v(p);
	}
    void build(int&p,int l,int r,int a[]){
        int mid=l+r>>1;/*用于已知序列排序后调用*/
        p=create(a[mid]);
        if(l<mid)build(l(p),l,mid-1);
        if(mid<r)build(r(p),mid+1,r);
        pushup(p);
    }
	void print(int p){
		if(l(p))print(l(p));
		std::cout<<v(p)<<" ";
		if(r(p))print(r(p));
	}
    inline void reset(int x){
        INF=x;
    }
    inline void build(int l,int r,int a[]){
        build(root,l,r,a);
    }
    inline void insert(int v){
		int x,y;
		split(root,x,y,v);
		merge(x,x,create(v));
		merge(root,x,y);
	}
    inline int kth(int x){
        return kth(root,x);
    }
	inline void del(int v){
		int x,y,p;
		split(root,x,y,v);
		split(x,x,p,v-1);
		int q=p;
		merge(p,l(p),r(p));/*抛弃了此区间根节点*/
		recycle(q);
		merge(x,x,p);
		merge(root,x,y);
	}
    inline void erase(int v){
		int x,y,p;
		split(root,x,y,v);
		split(x,x,p,v-1);/*抛弃了整个v的区间*/
        recycle(p);
		merge(root,x,y);
	}
    inline bool exist(int v){
		int x,y,p;
		split(root,x,y,v);
		split(x,x,p,v-1);
		bool re=w(p);
		merge(x,x,p);
		merge(root,x,y);
		return re;
	}
	inline int rank(int v){
		int x,y;
		split(root,x,y,v-1);
		int re=w(x)+1;
		merge(root,x,y);
		return re;
	}
	inline int pre(int v){
		int x,y;
		split(root,x,y,v-1);
		if(!x)return -INF;
		int re=kth(x,w(x));
		merge(root,x,y);
		return re;
	}
	inline int suc(int v){
		int x,y;
		split(root,x,y,v);
		if(!y)return INF;
		int re=kth(y,1);
		merge(root,x,y);
		return re;
	}
    inline void print(){
		print(root);
	}
	inline int size(){
		return t[root].sz;
	}
};

按排名分裂,文艺平衡树,一般需要用到懒惰标记,与线段树的标记类似。

支持区间最大值,区间翻转,区间加,维护哈希值。

template<const unsigned N,bool Max=false,bool Rev=false,bool Add=false,bool Hash=false>
class Treap{
    struct tree{
        int l,r,v,p,w,max,add,hs;
        bool rev;
        inline void clear(){
            memset(this,0,sizeof(*this));
        }
    }t[N];
    int root,tot,s[N],pw[N];
    #define l(p) (t[p].l)
    #define r(p) (t[p].r)
    #define v(p) (t[p].v)
    #define p(x) (t[x].p)
    #define w(p) (t[p].w)
    #define h(p) (t[p].hs)
    #define m(p) (t[p].max)
    #define a(p) (t[p].add)
    #define re(p) (t[p].rev)
	inline int rand(){
        static default_random_engine x;
        static uniform_int_distribution<int>f(-1e8,1e8);
        return f(x);
	}
    inline int create(int v){
        int x=s[0]?s[s[0]--]:++tot;
        t[x]={0,0,v,rand(),1,v,0,v,0};
        return x;
    }
    inline void recycle(int p){
        t[s[++s[0]]=p].clear();
    }
    inline void maxup(int p){
        m(p)=v(p);
        if(l(p))m(p)=max(m(l(p)),m(p));
        if(r(p))m(p)=max(m(r(p)),m(p));
    }
    inline void hashup(int p){
        h(p)=h(l(p))*pw[w(r(p))+1]+v(p)*pw[w(r(p))]+h(r(p));
    }
    inline void pushup(int p){
        w(p)=w(l(p))+w(r(p))+1;
        if(Max)maxup(p);
        if(Hash)hashup(p);
    }
    inline void revdown(int p){
        if(!re(p))return;
        re(p)=0;
        re(l(p))^=1;
        re(r(p))^=1;
        swap(l(p),r(p));
    }
    inline void adddown(int p){
        if(!a(p))return;
        int ad=a(p);
        a(p)=0;
        if(l(p)){
            a(l(p))+=ad;
            m(l(p))+=ad;
            v(l(p))+=ad;
        }
        if(r(p)){
            a(r(p))+=ad;
            m(r(p))+=ad;
            v(r(p))+=ad;
        }
    }
    inline void pushdown(int p){
        if(Rev)revdown(p);
        if(Add)adddown(p);
    }
    void split(int p,int&x,int&y,int k){
        if(!p)return x=y=0,void();
        if(Rev||Add)pushdown(p);
        if(w(l(p))<k)/*不取等,因为后面k-w(l(p))-1*/x=p,split(r(p),r(p),y,k-w(l(p))-1);
        else y=p,split(l(p),x,l(p),k);
        pushup(p);
    }
    void merge(int&p,int x,int y){
        if(!x||!y)return p=x|y,void();
        if(Rev||Add)pushdown(x),pushdown(y);
        if(p(x)<p(y))p=x,merge(r(p),r(p),y);
        else p=y,merge(l(p),x,l(p));
        pushup(p);
    }
    void print(int p){
        pushdown(p);
        if(l(p))print(l(p));
        cout<<v(p)<<' ';
        if(r(p))print(r(p));
    }
    inline int gethash(int l,int r){
        int x,y,p;
        split(root,x,y,r);
        split(x,x,p,l-1);
        int re=h(p);
        merge(x,x,p);
        merge(root,x,y);
        return re;
    }
    public:
    inline Treap(){
        tot=root=0;
        if(Hash){
            pw[0]=1;
            for(int i=1;i<N;i++)pw[i]=pw[i-1]*233;
        }
    }
    inline void build(int l,int r){
        for(int i=l;i<=r;i++)merge(root,root,create(i));
    }
    inline void build(int l,int r,char s[]){
        for(int i=l;i<=r;i++)merge(root,root,create(s[i]-'a'));
    }
    inline int getmax(int l,int r){
        int x,y,p;
        split(root,x,y,r);
        split(x,x,p,l-1);
        int re=m(p);
        merge(x,x,p);
        merge(root,x,y);
        return re;
    }
    inline void reverse(int l,int r){
        int x,y,p;
        split(root,x,y,r);
        split(x,x,p,l-1);
        re(p)^=1;
        merge(x,x,p);
        merge(root,x,y);
    }
    inline void add(int l,int r,int v){
        int x,y,p;
        split(root,x,y,r);
        split(x,x,p,l-1);
        v(p)+=v;
        m(p)+=v;
        a(p)+=v;
        merge(x,x,p);
        merge(root,x,y);
    }
    inline void insert(int x,int v){
        int y;
        split(root,x,y,x);
        merge(x,x,create(v));
        merge(root,x,y);
    }
    inline int lcq(int x,int y){
        if(x>y)swap(x,y);
        int l=1,r=w(root)-y+1,re=0;
        while(l<=r){
            int mid=l+r>>1;
            if(gethash(x,x+mid-1)==gethash(y,y+mid-1))re=mid,l=mid+1;
            else r=mid-1;
        }
        return re;
    }
    inline void replace(int x,int v){
        int y,p,k=x;
        split(root,x,y,k);
        split(x,x,p,k-1);
        h(p)=v(p)=v;
        merge(x,x,p);
        merge(root,x,y);
    }
    void print(){
        print(root);
    }
};

支持插入区间,删除,修改,区间翻转,区间求和,最大子列和。

#include<bits/stdc++.h>

using namespace std;
const int N=5e5+5;
struct treap{
	struct node{
		int p,v,sum,tma,lma,rma,cov,w,l,r;
		bool rev;
	}t[N];
	int tot,root,INF=0x7fffffff,s[N];
    #define l(p) (t[p].l)
    #define r(p) (t[p].r)
    #define v(p) (t[p].v)
    #define p(x) (t[x].p)
    #define w(p) (t[p].w)
    #define s(p) (t[p].sum)
    #define co(p) (t[p].cov)
    #define tm(p) (t[p].tma)
    #define lm(p) (t[p].lma)
    #define rm(p) (t[p].rma)
    #define re(p) (t[p].rev)
	inline void reset(int x){INF=x;}
	inline int rand(){
        static default_random_engine x;
        static uniform_int_distribution<int>f(-1e8,1e8);
        return f(x);
	}
	inline int create(int v){
	    int p=s[0]?s[s[0]--]:++tot;
	    t[p]={rand(),v,v,v,max(v,0),max(v,0),INF,1,0,0,0};
	    return p;
	}
	inline void pushup(int p){
		if(l(p)&&r(p)){
			w(p)=w(l(p))+w(r(p))+1;
			s(p)=s(l(p))+s(r(p))+v(p);
			tm(p)=max(rm(l(p))+v(p)+lm(r(p)),max(tm(l(p)),tm(r(p))));
			lm(p)=max(lm(l(p)),s(l(p))+v(p)+lm(r(p)));
			rm(p)=max(rm(r(p)),s(r(p))+v(p)+rm(l(p)));
		}
		else if(l(p)){
			w(p)=w(l(p))+1;
			s(p)=s(l(p))+v(p);
			tm(p)=max(tm(l(p)),rm(l(p))+v(p));
			lm(p)=max(0,max(lm(l(p)),s(l(p))+v(p)));
			rm(p)=max(0,v(p)+rm(l(p)));
		}
		else if(r(p)){
			w(p)=w(r(p))+1;
			s(p)=s(r(p))+v(p);
			tm(p)=max(tm(r(p)),v(p)+lm(r(p)));
			rm(p)=max(0,max(rm(r(p)),s(r(p))+v(p)));
			lm(p)=max(0,lm(r(p))+v(p));
		}
		else{
			w(p)=1;
			s(p)=tm(p)=v(p);
			lm(p)=rm(p)=max(v(p),0);
		}
	}
	inline int build(int n,int a[]){
	    int p,la=0;
		static int sta[N],top;
	    for(int i=1;i<=n;i++){
	        p=create(a[i]);
			la=0;
	        while(top&&p(sta[top])>p(p)){
	        	pushup(sta[top]);
	        	la=sta[top];
	        	sta[top--]=0;
			}
			if(top)t[sta[top]].r=p;
			l(p)=la;
			sta[++top]=p;
	    }
	    while(top)pushup(sta[top--]);
	    return sta[1];
	}
	void split(int p,int&x,int&y,int k){
		if(!p)return x=y=0,void();
		pushdown(p);
		if(w(l(p))<k)x=p,split(r(p),r(p),y,k-w(l(p))-1);
		else y=p,split(l(p),x,l(p),k);
		pushup(p);
	}
	void merge(int&p,int x,int y){
		if(!x||!y)return p=x|y,void();
		pushdown(x);
		pushdown(y);
		if(p(x)<p(y))p=x,merge(r(p),r(p),y);
		else p=y,merge(l(p),x,l(p));
		pushup(p);
	}
	inline void rev(int p){
		swap(l(p),r(p));
		swap(lm(p),rm(p));
        re(p)^=1;
	}
	inline void cov(int p,int v){
		v(p)=v;
		lm(p)=rm(p)=max(s(p)=w(p)*v,0);
		tm(p)=max(s(p),v(p));
        co(p)=v;
	}
	inline void pushdown(int p){
		if(re(p)){
			if(l(p))rev(l(p));
			if(r(p))rev(r(p));
		}
		if(co(p)!=INF){
			if(l(p))cov(l(p),t[p].cov);
			if(r(p))cov(r(p),t[p].cov);
		}
        re(p)=0;
        co(p)=INF;
	}
	inline void recycle(int p){
		if(!p)return;
        s[++s[0]]=p;
		recycle(l(p));
		recycle(r(p));
	}
	inline void insert(int pos,int n,int a[]){
		int x,y,rt=build(n,a);
		split(root,x,y,pos);
		merge(x,x,rt);
		merge(root,x,y);
	}
	inline void del(int pos,int n){
		int x,y,z;
		split(root,x,y,pos-1);
		split(y,y,z,n);
		merge(root,x,z);
		recycle(y);
	}
	inline void cover(int pos,int n,int v){
	    int x,y,z;
	    split(root,x,y,pos-1);
	    split(y,y,z,n);
	    cov(y,v);
	    merge(y,y,z);
	    merge(root,x,y);
	}
	inline void reverse(int pos,int n){
		int x,y,z;
		split(root,x,y,pos-1);
		split(y,y,z,n);
		rev(y);
		merge(y,y,z);
		merge(root,x,y);
	}
	inline int query(int pos,int n,bool f=0){
		int x,y,z;
		split(root,x,y,pos-1);
		split(y,y,z,n);
		int re=f?tm(y):s(y);
		merge(y,y,z);
		merge(root,x,y);
		return re;
	}
	inline int query(bool f=0){
		return f?tm(root):s(root);
	}
}treap;
int n,m,a[N];
char s[22];
signed main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",a+i);
    treap.root=treap.build(n,a);
    while(m--){
        scanf("%s",s);
        int p,x,y;
        if(s[0]=='I'){
            scanf("%d%d",&p,&x);
            int a[N];
            for(int i=1;i<=x;i++)cin>>a[i];
            treap.insert(p,x,a);
        }
        else if(s[0]=='D'){
            scanf("%d%d",&p,&x);
            treap.del(p,x);
        }
        else if(s[0]=='M'&&s[2]=='K'){
            scanf("%d%d%d",&p,&x,&y);
            treap.cover(p,x,y);
        }
        else if(s[0]=='R'){
            scanf("%d%d",&p,&x);
            treap.reverse(p,x);
        }
        else if(s[0]=='G'){
            scanf("%d%d",&p,&x);
            printf("%d\n",treap.query(p,x));
        }
        else printf("%d\n",treap.query(1));
    }
    return 0;
}

可持久化平衡树,对历史时间节点进行维护。

struct Treap{
    struct tree{
        int l,r,v,p,w;
    }t[N*50];
    int root[N],tot,inf=0x7fffffff;
    #define l(p) (t[p].l)
    #define r(p) (t[p].r)
    #define v(p) (t[p].v)
    #define p(x) (t[x].p)
    #define w(p) (t[p].w)
	inline int rand(){
        static default_random_engine x;
        static uniform_int_distribution<int>f(-1e8,1e8);
        return f(x);
	}
    inline int create(int v=0){
        t[++tot]={0,0,v,rand(),1};
        return tot;
    }
    inline void pushup(int p){
        w(p)=w(l(p))+w(r(p))+1;
    }
    void split(int p,int&x,int&y,int v){
        if(!p)return x=y=0,void();
        if(v(p)<=v){
            t[x=++tot]=t[p];/*分裂产生的新节点进行复制*/
            split(r(x),r(x),y,v);/*对新节点进行分裂*/
            pushup(x);
        }
        else{
            t[y=++tot]=t[p];
            split(l(y),x,l(y),v);
            pushup(y);
        }
    }
    void merge(int&p,int x,int y){
        if(!x||!y)return p=x|y,void();
        if(p(x)<p(y))t[p=++tot]=t[x]/*合并产生新节点进行复制*/,merge(r(p),r(p),y);
        else t[p=++tot]=t[y],merge(l(p),x,l(p));
        pushup(p);
    }
    inline int kt(int p,int x){
        while(w(l(p))+1!=x){
            if(x<=w(l(p)))p=l(p);
            else x-=w(l(p))+1,p=r(p);
        }
        return v(p);
    }
    inline void modify(int x,int y){
        root[x]=root[y];
    }
    inline void insert(int p,int v){
        int x,y;
        split(root[p],x,y,v);/*根节点传p对应的根,这样是引用的效果*/
        merge(x,x,create(v));
        merge(root[p],x,y);
    }
    inline void del(int p,int v){
        int x,y,z;
        split(root[p],x,z,v);
        split(x,x,y,v-1);
        merge(y,l(y),r(y));
        merge(x,x,y);
        merge(root[p],x,z);
    }
    inline int rank(int p,int v){
        int x,y;
        split(root[p],x,y,v-1);
        int re=w(x)+1;
        merge(root[p],x,y);
        return re;
    }
    inline int kth(int p,int x){
        return kt(root[p],x);
    }
    inline int pre(int p,int v){
        int x,y;
        split(root[p],x,y,v-1);
        if(!x)return -inf;
        int re=kt(x,w(x));
        merge(root[p],x,y);
        return re;
    }
    inline int suc(int p,int v){
        int x,y;
        split(root[p],x,y,v);
        if(!y)return inf;
        int re=kt(y,1);
        merge(root[p],x,y);
        return re;
    }
};

可持久化文艺平衡树。

对历史时间节点进行维护,支持插入、删除、区间翻转、区间求和。

struct Treap{
    struct tree{
        int l,r,v,p,w;
        long long sum;
        bool rev;
    }t[N<<7];
    int root[N],tot,s[N];
    #define l(p) (t[p].l)
    #define r(p) (t[p].r)
    #define v(p) (t[p].v)
    #define p(x) (t[x].p)
    #define w(p) (t[p].w)
    #define s(p) (t[p].sum)
    #define re(p) (t[p].rev)
	inline int rand(){
        static default_random_engine x;
        static uniform_int_distribution<int>f(-1e8,1e8);
        return f(x);
	}
    inline void recycle(int p){
        t[s[++s[0]]=p];/*这里最好不要清空了,之前版本可能会用到*/
    }
    inline int create(int v){
        int p=s[0]?s[s[0]--]:++tot;
        t[p]={0,0,v,rand(),1,v,0};
        return p;
    }
    inline int create(){
        return s[0]?s[s[0]--]:++tot;
    }
    inline void pushup(int p){
        w(p)=w(l(p))+w(r(p))+1;
        s(p)=s(l(p))+s(r(p))+v(p);/*注意要加上自己的权值*/
    }
    inline void pushdown(int p){
        if(!re(p))return;
        swap(l(p),r(p));
        re(p)=0;
        if(l(p)){/*没有节点则不进行下放*/
            t[l(p)=create()]=t[l(p)];/*在标记下放时也要进行新建节点*/
            re(l(p))^=1;
        }
        if(r(p)){
            t[r(p)=create()]=t[r(p)];
            re(r(p))^=1;
        }
    }
    void split(int p,int&x,int&y,int k){
        if(!p)return x=y=0,void();
        pushdown(p);
        if(w(l(p))<k){
            t[x=create()]=t[p];
            split(r(x),r(x),y,k-w(l(x))-1);
            pushup(x);
        }
        else{
            t[y=create()]=t[p];
            split(l(y),x,l(y),k);/*对复制后的节点进行分裂,原先节点不动*/
            pushup(y);
        }
    }
    void merge(int&p,int x,int y){
        if(!x||!y)return p=x|y,void();
        pushdown(x);
        pushdown(y);
        if(p(x)<p(y))p=x,merge(r(p),r(p),y);
        else p=y,merge(l(p),x,l(p));
        pushup(p);/*split和merge一一对应,所以不需要再复制*/
    }
    inline void modify(int x,int y){
        root[x]=root[y];
    }
    inline void insert(int p,int k,int v){
        int x,y;
        split(root[p],x,y,k);
        merge(x,x,create(v));
        merge(root[p],x,y);
    }
    inline void del(int p,int k){
        int x,y;
        split(root[p],x,y,k);
        split(x,x,k,k-1);
        recycle(k);
        merge(root[p],x,y);
    }
    inline void reverse(int p,int l,int r){
        int x,y,z;
        split(root[p],x,y,l-1);
        split(y,y,z,r-l+1);
        re(y)^=1;
        merge(y,y,z);
        merge(root[p],x,y);
    }
    inline long long getsum(int p,int l,int r){
        int x,y,z;
        split(root[p],x,y,l-1);
        split(y,y,z,r-l+1);
        long long re=s(y);
        merge(y,y,z);
        merge(root[p],x,y);
        return re;
    }
};
posted @ 2022-11-18 20:54  半步蒟蒻  阅读(100)  评论(0)    收藏  举报