无旋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;
}
};