bzoj 3224 普通的平衡树操作
splay树
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define PI acos(-1.0)
typedef long long ll;
typedef long double ld;
const int maxn=1e6+10;
struct Tree
{
int son[2],pre,key,num,size;
Tree(){}
Tree(int a,int b,int c,int d)
{
pre=a;
key=b;
num=c;
size=d;
son[0]=son[1]=0;
}
}t[maxn];
int cnt=1,rt=0;
inline void push_up(int x)
{
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+t[x].num;
}
inline void Rotate(int x,int p) //0左旋,1右旋
{
int y=t[x].pre;
t[y].son[!p]=t[x].son[p];
t[t[x].son[p]].pre=y;
t[x].pre=t[y].pre;
if(t[x].pre)
t[t[x].pre].son[t[t[x].pre].son[1]==y]=x;
t[x].son[p]=y;
t[y].pre=x;
push_up(y);
push_up(x);
}
inline void Splay(int x,int to) //将节点x移成to的子节点
{
while(t[x].pre!=to)
{
int y=t[x].pre;
int z=t[y].pre;
if(z==to)
Rotate(x,t[y].son[0]==x);
else
{
int p=(t[z].son[0]==y);
if(t[y].son[p]==x)
{
Rotate(x,!p); //之字形
Rotate(x,p);
}
else
{
Rotate(y,p); //一字形
Rotate(x,p);
}
}
}
if(to==0)
rt=x;
}
inline int Find(int key) //返回值为key的节点
{
int x=rt;
while(x&&key!=t[x].key)
x=t[x].son[key>t[x].key];
if(x)
Splay(x,0);
return x;
}
inline void Insert(int key) //插入值为key的节点,并将该节点移成根
{
if(!rt)
{
rt=cnt;
t[cnt++]=Tree(0,key,1,1);
return;
}
int x=rt,y=0;
while(x&&t[x].key!=key)
{
y=x;
x=t[x].son[key>t[x].key];
}
if(x)
{
t[x].num++;
Splay(x,0);
return;
}
x=cnt;
t[cnt].num=1;
t[cnt++]=Tree(y,key,1,1);
t[y].son[key>t[y].key]=x;
Splay(x,0);
}
inline void Delete(int key) //删除值为key的节点,并将该节点的前驱移成根
{
int x=Find(key);
if(!x)
return;
if(t[x].num>1)
{
t[x].num--;
Splay(x,0);
return;
}
int y=t[x].son[0];
while(t[y].son[1])
y=t[y].son[1];
int z=t[x].son[1];
while(t[z].son[0])
z=t[z].son[0];
if(!y&&!z)
{
rt=0;
return;
}
if(!y)
{
Splay(z,0);
t[z].son[0]=0;
push_up(z);
return;
}
if(!z)
{
Splay(y,0);
t[y].son[1]=0;
push_up(y);
return;
}
Splay(y,0);
Splay(z,y);
t[z].son[0]=0;
push_up(z);
push_up(y);
}
inline int GetKth(int k) //寻找第k小的值,并将该节点移成根
{
if(!rt||k>t[rt].size)
return 0;
int x=rt,y=0;
while(true)
{
y=t[x].son[0];
if(t[y].size+t[x].num<k)
{
k-=(t[y].size+t[x].num);
x=t[x].son[1];
}
else if(t[y].size>=k)
x=y;
else
{
Splay(x,0);
return t[x].key;
}
}
}
inline int Rank(int key) //寻找值为key是第几小
{
int x=rt,ans=0;
while(true)
{
if(key<t[x].key)
x=t[x].son[0];
else
{
if(t[t[x].son[0]].size>0)
ans+=t[t[x].son[0]].size;
if(key==t[x].key)
{
Splay(x,0);
return ans+1;
}
ans+=t[x].num;
x=t[x].son[1];
}
}
}
inline int Prev() //寻找小于根节点的最大值的节点,并将该节点移成根
{
int x=t[rt].son[0];
if(!x)
return 0;
while(t[x].son[1])
x=t[x].son[1];
return t[x].key;
}
inline int Succ() //寻找大于根节点的最小值的节点,并将该节点移成根
{
int x=t[rt].son[1];
if(!x)
return 0;
while(t[x].son[0])
x=t[x].son[0];
return t[x].key;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==1)
Insert(x);
else if(op==2)
Delete(x);
else if(op==3)
printf("%d\n",Rank(x));
else if(op==4)
printf("%d\n",GetKth(x));
else if(op==5)
{
Insert(x);
printf("%d\n",Prev());
Delete(x);
}
else
{
Insert(x);
printf("%d\n",Succ());
Delete(x);
}
}
return 0;
}
区间操作
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define inf 0x3f3f3f3f
#define key_value ch[ch[root][1]][0]
typedef long long ll;
typedef long double ld;
const int maxn=5e5+10;
int pre[maxn],ch[maxn][2],val[maxn],size[maxn];
int root,tot;
int sum[maxn],rev[maxn],same[maxn],lazy[maxn];
int minn[maxn],maxx[maxn];
int lx[maxn],rx[maxn],mx[maxn];
int a[maxn],n,q;
int s[maxn],cnt;//内存池和容量
void Newnode(int &r,int father,int k)
{
if(cnt)
r=s[cnt--];
else
r=++tot;
pre[r]=father;
ch[r][0]=ch[r][1]=0;
val[r]=sum[r]=k;
minn[r]=maxx[r]=k;
rev[r]=same[r]=0;
lx[r]=rx[r]=mx[r]=k;
size[r]=1;
}
void Update_Rev(int r)
{
if(!r)
return;
swap(ch[r][0],ch[r][1]);
swap(lx[r],rx[r]);
rev[r]^=1;
}
void Update_Same(int r,int v)
{
if(!r)
return;
val[r]=v;
sum[r]=v*size[r];
lx[r]=rx[r]=mx[r]=max(v,v*size[r]);
minn[r]=maxx[r]=v;
same[r]=1;
}
void Update_Add(int r,int v)
{
if(!r)
return;
val[r]+=v;
sum[r]+=v*size[r];
lx[r]=rx[r]=mx[r]=max(val[r],val[r]*size[r]);
maxx[r]+=v;
minn[r]+=v;
lazy[r]+=v;
}
void push_up(int r)
{
int lson=ch[r][0],rson=ch[r][1];
size[r]=size[lson]+size[rson]+1;
sum[r]=sum[lson]+sum[rson]+val[r];
minn[r]=val[r],maxx[r]=val[r];
minn[r]=min(min(minn[lson],minn[rson]),minn[r]);
maxx[r]=max(max(maxx[lson],maxx[rson]),maxx[r]);
lx[r]=max(lx[lson],sum[lson]+val[r]+max(0,lx[rson]));
rx[r]=max(rx[rson],sum[rson]+val[r]+max(0,rx[lson]));
mx[r]=max(0,rx[lson])+val[r]+max(0,lx[rson]);
mx[r]=max(mx[r],max(mx[lson],mx[rson]));
}
void push_down(int r)
{
if(same[r])
{
Update_Same(ch[r][0],val[r]);
Update_Same(ch[r][1],val[r]);
same[r]=0;
}
if(rev[r])
{
Update_Rev(ch[r][0]);
Update_Rev(ch[r][1]);
rev[r]=0;
}
if(lazy[r])
{
Update_Add(ch[r][0],lazy[r]);
Update_Add(ch[r][1],lazy[r]);
lazy[r]=0;
}
}
void Build(int &rt,int l,int r,int father)
{
if(l>r)
return;
int mid=(l+r)/2;
Newnode(rt,father,a[mid]);
Build(ch[rt][0],l,mid-1,rt);
Build(ch[rt][1],mid+1,r,rt);
push_up(rt);
}
void Init()
{
root=tot=cnt=0;
ch[root][0]=ch[root][1]=0;
size[root]=pre[root]=0;
lx[root]=rx[root]=mx[root]=-inf;
same[root]=lazy[root]=rev[root]=0;
sum[root]=val[root]=0;
minn[root]=inf;
maxx[root]=-inf;
Newnode(root,0,-1);
Newnode(ch[root][1],root,-1);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
Build(key_value,0,n-1,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
void Rotate(int x,int p) //0为左旋,1为右旋
{
int y=pre[x],z=pre[y];
push_down(y);
push_down(x);
ch[y][!p]=ch[x][p];
pre[ch[x][p]]=y;
if(z)
ch[z][ch[z][1]==y]=x;
pre[x]=pre[y];
ch[x][p]=y;
pre[y]=x;
push_up(y);
push_up(x);
}
void Splay(int x,int to) //将x结点转移至to下面
{
push_down(x);
while(pre[x]!=to)
{
int y=pre[x],z=pre[y];
if(z==to)
{
push_down(y);
push_down(x);
Rotate(x,ch[y][0]==x);
}
else
{
push_down(z);
push_down(y);
push_down(x);
int p=ch[z][0]==y;
if(ch[y][p]==x)
Rotate(x,!p);
else
Rotate(y,p);
Rotate(x,p);
}
}
push_up(x);
if(to==0)
root=x;
}
int Kth(int r,int k) //找到序列中第k位在树中的位置
{
push_down(r);
int t=size[ch[r][0]]+1;
if(t==k)
return r;
if(t>k)
return Kth(ch[r][0],k);
else
return Kth(ch[r][1],k-t);
}
void Split(int x,int y)
{
Splay(x,0);
Splay(y,root);
}
void Insert(int pos,int num) //从第pos个数开始插入num个数
{
for(int i=0; i<num; i++)
scanf("%d",&a[i]);
int x=Kth(root,pos+1);
//cout << val[10] << endl;
int y=Kth(root,pos+2);
Split(x,y);
Build(key_value,0,num-1,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
void Erase(int r) //删除子树
{
if(!r)
return;
s[++cnt]=r;
Erase(ch[r][0]);
Erase(ch[r][1]);
}
void Delete(int pos,int num) //从第pos个数开始删除num个数
{
int x=Kth(root,pos),y=Kth(root,pos+num+1);
Split(x,y);
Erase(key_value);
pre[key_value]=0;
key_value=0;
push_up(ch[root][1]);
push_up(root);
}
void Add(int pos,int num,int v) //从第pos个数开始num个数都加上v
{
int x=Kth(root,pos),y=Kth(root,pos+num+1);
Split(x,y);
Update_Add(key_value,v);
push_up(ch[root][1]);
push_up(root);
}
void Make_Same(int pos,int num,int c) //从第pos个数开始将num个数置为0
{
int x=Kth(root,pos),y=Kth(root,pos+num+1);
Split(x,y);
Update_Same(key_value,c);
push_up(ch[root][1]);
push_up(root);
}
void Reverse(int pos,int num) //从第pos个数开始的num个数进行区间翻转
{
int x=Kth(root,pos),y=Kth(root,pos+num+1);
Split(x,y);
Update_Rev(key_value);
push_up(ch[root][1]);
push_up(root);
}
//将区间l-r向右循环平移d次,l1=l,r1=r-d,l2=r-d+1,r2=r,d%=(r-l+1)(d>0)
void Revolve(int l1,int r1,int l2,int r2)
{
int x=Kth(root,l2),y=Kth(root,r2+2);
Split(x,y);
int temp=key_value;
key_value=0;
x=Kth(root,l1),y=Kth(root,l1+1);
Split(x,y);
key_value=temp;
pre[temp]=ch[root][1];
push_up(ch[root][1]);
push_up(root);
}
int Sum(int pos,int num) //从第pos个数开始num个数之和
{
int x=Kth(root,pos),y=Kth(root,pos+num+1);
Split(x,y);
return sum[key_value];
}
int MaxSum(int pos,int num) //从第pos个数开始的num个数中最大子段和
{
int x=Kth(root,pos),y=Kth(root,pos+num+1);
Split(x,y);
return mx[key_value];
}
int Min(int l,int r)
{
int x=Kth(root,l),y=Kth(root,r+2);
Split(x,y);
return minn[key_value];
}
int Max(int l,int r)
{
int x=Kth(root,l),y=Kth(root,r+2);
Split(x,y);
return maxx[key_value];
}
void InOrder(int r)
{
if(!r)
return;
push_down(r);
InOrder(ch[r][0]);
printf("%d ",val[r]);
InOrder(ch[r][1]);
}
int main()
{
scanf("%d%d",&n,&q);
Init();
while(q--)
{
char str[100];
scanf("%s",str);
int pos,t;
if(str[0]=='I')
{
scanf("%d%d",&pos,&t);
Insert(pos,t);
}
else if(str[0]=='D')
{
scanf("%d%d",&pos,&t);
Delete(pos,t);
}
else if(str[0]=='M'&&str[2]=='K')
{
int c;
scanf("%d%d%d",&pos,&t,&c);
Make_Same(pos,t,c);
}
else if(str[0]=='R')
{
scanf("%d%d",&pos,&t);
Reverse(pos,t);
}
else if(str[0]=='G')
{
scanf("%d%d",&pos,&t);
printf("%d\n",Sum(pos,t));
}
else
printf("%d\n",MaxSum(1,size[root]-2));
// InOrder(root);
// puts("");
}
return 0;
}
treap树
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define PI acos(-1.0)
typedef long long ll;
typedef long double ld;
const int maxn=1e6+10;
int ans;
struct Tree
{
int son[2],key,num,size,rnd;
Tree(){}
Tree(int b,int c,int d,int e)
{
key=b;
num=c;
size=d;
rnd=e;
son[0]=son[1]=0;
}
}t[maxn];
int cnt=1,rt=0;
void push_up(int x)
{
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+t[x].num;
}
void Rotate(int &x,int p) //0右旋,1左旋旋
{
int y=t[x].son[p];
t[x].son[p]=t[y].son[!p];
t[y].son[!p]=x;
push_up(x);
push_up(y);
x=y;
}
void Insert(int &x,int key)
{
if(!x)
{
x=cnt;
t[cnt++]=Tree(key,1,1,rand());
return;
}
t[x].size++;
if(t[x].key==key)
{
t[x].num++;
return;
}
Insert(t[x].son[key>t[x].key],key);
if(t[t[x].son[key>t[x].key]].rnd<t[x].rnd)
Rotate(x,key>t[x].key);
}
void Delete(int &x,int key)
{
if(!x)
return;
if(t[x].key==key)
{
if(t[x].num>1)
{
t[x].num--;
t[x].size--;
return;
}
if(t[x].son[0]==0||t[x].son[1]==0)
x=t[x].son[0]+t[x].son[1];
else
{
Rotate(x,t[t[x].son[0]].rnd>=t[t[x].son[1]].rnd);
Delete(x,key);
}
}
else
{
t[x].size--;
Delete(t[x].son[key>t[x].key],key);
}
}
int GetKth(int x,int k)
{
if(!x)
return 0;
if(k<=t[t[x].son[0]].size)
return GetKth(t[x].son[0],k);
else if(k>t[t[x].son[0]].size+t[x].num)
return GetKth(t[x].son[1],k-t[t[x].son[0]].size-t[x].num);
else
return t[x].key;
}
int Rank(int x,int key) //寻找值为key是第几小
{
if(!x)
return 0;
if(t[x].key==key)
return t[t[x].son[0]].size+1;
else if(key>t[x].key)
return t[t[x].son[0]].size+t[x].num+Rank(t[x].son[1],key);
else
return Rank(t[x].son[0],key);
}
void Prev(int x,int key)
{
if(!x)
return;
if(t[x].key<key)
{
ans=x;
Prev(t[x].son[1],key);
}
else
Prev(t[x].son[0],key);
}
void Succ(int x,int key)
{
if(!x)
return;
if(t[x].key>key)
{
ans=x;
Succ(t[x].son[0],key);
}
else
Succ(t[x].son[1],key);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==1)
Insert(rt,x);
else if(op==2)
Delete(rt,x);
else if(op==3)
printf("%d\n",Rank(rt,x));
else if(op==4)
printf("%d\n",GetKth(rt,x));
else if(op==5)
{
ans=0;
Prev(rt,x);
printf("%d\n",t[ans].key);
}
else
{
ans=0;
Succ(rt,x);
printf("%d\n",t[ans].key);
}
}
return 0;
}