平衡树
\(\operatorname{Treap}\)
(有时间就补
点击查看代码
//Treap
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
using namespace std;
mt19937 srd(time(0));
cs int N=1e6+3,inf=0x3f3f3f3f;
int n,cnt,rt;
struct Treap{int son[2],cnt,size,val,rnd;}t[N];
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) pc('-'),x=-x;if(x>9) wt(x/10);pc(x%10|48);}
il void upd(cs int x){t[x].size=t[x].cnt+t[t[x].son[1]].size+t[t[x].son[0]].size;}
il void rotate(int &x,cs int dir)
{
int s=t[x].son[dir];
t[x].son[dir]=t[s].son[dir^1],
t[s].son[dir^1]=x,upd(x),upd(s),x=s;
}
void insert(int &x,cs int val)
{
if(!x)
return x=++cnt,t[x].val=val,
t[x].rnd=srd(),t[x].size=t[x].cnt=1,void();
++t[x].size;
if(t[x].val==val) return t[x].cnt++,void();
int dir=t[x].val<val;insert(t[x].son[dir],val);
if(t[x].rnd>t[t[x].son[dir]].rnd) rotate(x,dir);
upd(x);//1
}
void delet(int &x,cs int val)
{
if(!x) return;
if(t[x].val==val)
{
if(t[x].cnt>1) return t[x].cnt--,t[x].size--,void();
bool dir=t[t[x].son[0]].rnd>t[t[x].son[1]].rnd;
if(t[x].son[0]==0||t[x].son[1]==0) x=t[x].son[0]+t[x].son[1];
else rotate(x,dir),delet(x,val);
}
else t[x].size--,delet(t[x].son[t[x].val<val],val);
upd(x);//2
}
int rk(cs int x,int val)
{
if(!x) return 0;
if(t[x].val==val) return t[t[x].son[0]].size+1;
if(t[x].val>val) return rk(t[x].son[0],val);
return rk(t[x].son[1],val)+t[t[x].son[0]].size+t[x].cnt;
}
il int kth(cs int x,cs int k)
{
if(!x) return 0;
if(t[t[x].son[0]].size>=k) return kth(t[x].son[0],k);
if(t[t[x].son[0]].size+t[x].cnt>=k) return t[x].val;
return kth(t[x].son[1],k-t[t[x].son[0]].size-t[x].cnt);
}
int pre(cs int x,cs int val)
{
if(!x) return -inf;
if(t[x].val>=val) return pre(t[x].son[0],val);
return max(pre(t[x].son[1],val),t[x].val);
}
int nxt(cs int x,cs int val)
{
if(!x) return inf;
if(t[x].val<=val) return nxt(t[x].son[1],val);
return min(t[x].val,nxt(t[x].son[0],val));
}
int main()
{
read(n);
for(ri int o=1,opt,x;o<=n;++o)
{
read(opt),read(x);
if(opt==1) insert(rt,x);
else if(opt==2) delet(rt,x);
else if(opt==3) wt(rk(rt,x)),pc('\n');
else if(opt==4) wt(kth(rt,x)),pc('\n');
else if(opt==5) wt(pre(rt,x)),pc('\n');
else wt(nxt(rt,x)),pc('\n');
}
return 0;
}
\(\operatorname{fhq-Treap}\)
(有时间就补
点击查看代码
//fhq_Treap
#include<bits/stdc++.h>
#define cs const
#define il inline
#define LL long long
#define pc(i) putchar(i)
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k) for(int i=(j);(i)>=(k);--(i))
using namespace std;
mt19937 srd(time(0));
cs int inf=0x3f3f3f3f,N=5e5+7;
int FL,CH;
template<typename T> bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
int in(T&a,Args&...args){return in(a)+in(args...);}
void wt(int x){if(x<0)x=-x,pc('-');if(x>9)wt(x/10);pc(x%10|48);}
namespace Treap
{
#define ls(i) (t[i].son[0])
#define rs(i) (t[i].son[1])
struct fhq{int son[2],val,rnd,sz;}t[N]; int cnt=0;
il int newnode(cs int val)
{ return t[++cnt].sz=1,t[cnt].rnd=srd(),t[cnt].val=val,cnt; }
il void pushup(cs int x) { t[x].sz=t[ls(x)].sz+t[rs(x)].sz+1; }
void split(cs int cur,cs int k,int &x,int &y)
{
if(!cur) return x=y =0,void();
if(t[cur].val<=k) x=cur,split(rs(cur),k,rs(cur),y);
else y=cur,split(ls(cur),k,x,ls(cur));
pushup(cur);
}
il int merge(cs int x,cs int y)
{
if(!x||!y) return x+y;
if(t[x].rnd<t[y].rnd) return rs(x)=merge(rs(x),y),pushup(x),x;
else return ls(y)=merge(x,ls(y)),pushup(y),y;
}
il int kth(int x,int k)
{
while(1)
if(k<=t[ls(x)].sz) x=ls(x);
else if(k==t[ls(x)].sz+1) return x;
else k-=t[ls(x)].sz+1,x=rs(x);
}
}using namespace Treap;
int rt ,Q;
signed main()
{
in(Q);
while(Q--)
{
int op,x,y,z,a; in(op,a);
if(op==1) split(rt,a,x,y),rt=merge(merge(x,newnode(a)),y);
else if(op==2) split(rt,a,x,z),split(x,a-1,x,y),y=merge(ls(y),rs(y)),rt=merge(merge(x,y),z);
else if(op==3) split(rt,a-1,x,y),wt(t[x].sz+1),pc('\n'),rt=merge(x,y);
else if(op==4) wt(t[kth(rt,a)].val),pc('\n');
else if(op==5) split(rt,a-1,x,y),wt(t[kth(x,t[x].sz)].val),pc('\n'),rt=merge(x,y);
else split(rt,a,x,y),wt(t[kth(y,1)].val),pc('\n'),rt=merge(x,y);
}
return 0;
}
\(\operatorname{Splay}\)
基本操作
maintain(x):在改变节点位置后,将节点 \(x\) 的 \(\text{size}\) 更新。
get(x):判断节点 \(x\) 是父亲节点的左儿子还是右儿子。
clear(x):销毁节点 \(x\)。
旋转
不能破坏二叉查找树的性质
root 必须指向旋转后的根节点

\(\operatorname{Splay}\) 操作
\(\operatorname{Splay}\) 操作规定:每访问一个节点\(x\) 后都要强制将其旋转到根节点。
\(\operatorname{Splay}\) 操作即对 \(x\) 做一系列的 \(\operatorname{Splay}\) 步骤。每次对 \(x\) 做一次 \(\operatorname{Splay}\) 步骤,\(x\) 到根节点的距离都会更近。定义 \(p\) 为 \(x\) 的父节点。\(\operatorname{Splay}\) 步骤有三种,具体分为六种情况:
- \(zig\)操作:\(p\)为根(最后一步)

- \(zig-zag\)操作:\(p\)非根,\(x,p\)为同侧子节点

- \(zig-zag\)操作:\(p\)非根,\(x,p\)为异侧子节点

插入
- 如果树空了,则直接插入根并退出。
- 如果当前节点的权值等于 \(k\) 则增加当前节点的大小并更新节点和父亲的信息,将当前节点进行 \(\operatorname{Splay}\) 操作。
- 否则按照二叉查找树的性质向下找,找到空节点就插入即可
注意最后需要进行 \(\operatorname{Splay}\) 操作。
查询 \(x\) 的排名
根据二叉查找树的定义和性质
- 如果 \(x\) 比当前节点的权值小,向其左子树查找。
- 如果 \(x\) 比当前节点的权值大,将答案加上左子树(\(size\))和当前节点(\(cnt\))的大小,向其右子树查找。
- 如果 \(x\) 与当前节点的权值相同,将答案加 \(1\) 并返回。
查询\(x\)的前驱
可以转化为:将 \(x\) 插入(此时 \(x\) 已经在根的位置了),前驱即为 \(x\) 的左子树中最右边的节点,最后将 \(x\) 删除即可。
注意最后需要进行 \(\operatorname{Splay}\) 操作。
查询\(x\)的后继
可以转化为:将 \(x\) 插入(此时 \(x\) 已经在根的位置了),后继即为 \(x\) 的右子树中最左边的节点,最后将 \(x\) 删除即可。
注意最后需要进行 \(\operatorname{Splay}\) 操作。
合并两棵树
合并两棵 \(\operatorname{Splay}\) 树,设两棵树的根节点分别为 \(x\) 和 \(y\),那么我们要求 \(x\) 树中的最大值小于 \(y\) 树中的最小值。合并操作如下:
- 如果 \(x\) 和 \(y\) 其中之一或两者都为空树,直接返回不为空的那一棵树的根节点或空树。
- 否则将 \(x\) 树中的最大值 $$\operatorname{Splay}$$ 到根,然后把它的右子树设置为 y 并更新节点的信息,然后返回这个节点。
删除
首先将 \(x\) 旋转到根的位置。(通过rk()即可)
- 如果 \(cnt[x]>1\)(有不止一个 \(x\)),那么将 \(cnt[x]\) 减 \(1\) 并退出。
- 否则,合并它的左右两棵子树即可。

$\large Click\space to\space view\space the\space code:$
//Splay
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
using namespace std;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
cs int N=1e5+7;
int n,m,lst,ans,rt,tot,fa[N],val[N],ch[N][2],cnt[N],sz[N];
struct Splay{
il void maintain(cs int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];}//upd:size
il bool get(cs int x){return x==ch[fa[x]][1];}//x: ls or rs
il void clear(cs int x){ch[x][0]=ch[x][1]=fa[x]=val[x]=sz[x]=cnt[x]=0;}
il void rotate(cs int x)
{
int y=fa[x],z=fa[y],dir=get(x);
ch[y][dir]=ch[x][dir^1];
if(ch[x][dir^1]) fa[ch[x][dir^1]]=y;
ch[x][dir^1]=y,fa[y]=x,fa[x]=z;
if(z) ch[z][y==ch[z][1]]=x;
maintain(y),maintain(x);
}
il void splay(cs int x)
{
for(ri int f=fa[x];f=fa[x],f;rotate(x))
if(fa[f]) rotate(get(x)==get(f)?f:x);
rt=x;
}
il void ins(cs int k)
{
if(!rt)
return val[++tot]=k,cnt[tot]++,
rt=tot,maintain(rt),void();
int cur=rt,f=0;
while(1)
{
if(val[cur]==k)
{
cnt[cur]++,maintain(cur),maintain(f),
splay(cur);break;
}
f=cur,cur=ch[cur][val[cur]<k];
if(!cur)
{
val[++tot]=k,cnt[tot]++,
fa[tot]=f,ch[f][val[f]<k]=tot,
maintain(tot),maintain(f),
splay(tot);break;
}
}
}
il int rk(cs int k)
{
int re=0,cur=rt;
while(1)
{
if(k<val[cur]) cur=ch[cur][0];
else
{
re+=sz[ch[cur][0]];
if(k==val[cur]) return splay(cur),re+1;
re+=cnt[cur],cur=ch[cur][1];
}
}
}
il int kth(int k)
{
int cur=rt;
while(1)
{
if(ch[cur][0]&&k<=sz[ch[cur][0]]) cur=ch[cur][0];
else
{
k-=cnt[cur]+sz[ch[cur][0]];
if(k<=0) return splay(cur),val[cur];
cur=ch[cur][1];
}
}
}
il int pre()
{
int cur=ch[rt][0];
if(!cur) return cur;
while(ch[cur][1]) cur=ch[cur][1];
return splay(cur),cur;
}
il int nxt()
{
int cur=ch[rt][1];
if(!cur) return cur;
while(ch[cur][0]) cur=ch[cur][0];
return splay(cur),cur;
}
il void del(cs int k)
{
rk(k);
if(cnt[rt]>1) return cnt[rt]--,maintain(rt),void();
if(!ch[rt][0]&&!ch[rt][1]) return clear(rt),rt=0,void();
if(!ch[rt][0])
{
int cur=rt;rt=ch[rt][1];
fa[rt]=0,clear(cur);return;
}
if(!ch[rt][1])
{
int cur=rt;rt=ch[rt][0];
fa[rt]=0,clear(cur);return;
}
int cur=rt,x=pre();
fa[ch[cur][1]]=x,ch[x][1]=ch[cur][1];
clear(cur),maintain(rt);
}
}t;
signed main()
{
read(n);
for(ri int i=1,x,op;i<=n;++i)
{
read(op),read(x);
if(op==1) t.ins(x);
else if(op==2) t.del(x);
else if(op==3) wt(t.rk(x)),pc('\n');
else if(op==4) wt(t.kth(x)),pc('\n');
else if(op==5) t.ins(x),t.pre(),wt(val[rt]),t.del(x),pc('\n');
else t.ins(x),t.nxt(),wt(val[rt]),t.del(x),pc('\n');
}
return 0;
}
$\large Click\space to\space view\space the\space code:$
//Splay
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
cs int N=2e6+7;
int n,m,lst,ans,rt,tot,fa[N],val[N],ch[N][2],cnt[N],sz[N];
struct Splay{
il void maintain(cs int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];}//upd:size
il bool get(cs int x){return x==ch[fa[x]][1];}//x: ls or rs
il void clear(cs int x){ch[x][0]=ch[x][1]=fa[x]=val[x]=sz[x]=cnt[x]=0;}
il void rotate(cs int x)
{
int y=fa[x],z=fa[y],dir=get(x);
ch[y][dir]=ch[x][dir^1];
if(ch[x][dir^1]) fa[ch[x][dir^1]]=y;
ch[x][dir^1]=y,fa[y]=x,fa[x]=z;
if(z) ch[z][y==ch[z][1]]=x;
maintain(y),maintain(x);
}
il void splay(cs int x)
{
for(ri int f=fa[x];f=fa[x],f;rotate(x))
if(fa[f]) rotate(get(x)==get(f)?f:x);
rt=x;
}
il void ins(cs int k)
{
if(!rt)
return val[++tot]=k,cnt[tot]++,
rt=tot,maintain(rt),void();
int cur=rt,f=0;
while(1)
{
if(val[cur]==k)
{
cnt[cur]++,maintain(cur),maintain(f),
splay(cur);break;
}
f=cur,cur=ch[cur][val[cur]<k];
if(!cur)
{
val[++tot]=k,cnt[tot]++,
fa[tot]=f,ch[f][val[f]<k]=tot,
maintain(tot),maintain(f),
splay(tot);break;
}
}
}
il int rk(cs int k)
{
int re=0,cur=rt;
while(cur)
{
if(k<val[cur]) cur=ch[cur][0];
else
{
re+=sz[ch[cur][0]];
if(k==val[cur]) return splay(cur),re+1;
re+=cnt[cur],cur=ch[cur][1];
}
}
return re+1;
}
il int kth(int k)
{
int cur=rt;
while(1)
{
if(ch[cur][0]&&k<=sz[ch[cur][0]]) cur=ch[cur][0];
else
{
k-=cnt[cur]+sz[ch[cur][0]];
if(k<=0) return splay(cur),val[cur];
cur=ch[cur][1];
}
}
}
il int pre()
{
int cur=ch[rt][0];
if(!cur) return cur;
while(ch[cur][1]) cur=ch[cur][1];
return splay(cur),cur;
}
il int nxt()
{
int cur=ch[rt][1];
if(!cur) return cur;
while(ch[cur][0]) cur=ch[cur][0];
return splay(cur),cur;
}
il void del(cs int k)
{
rk(k);
if(cnt[rt]>1) return cnt[rt]--,maintain(rt),void();
if(!ch[rt][0]&&!ch[rt][1]) return clear(rt),rt=0,void();
if(!ch[rt][0])
{
int cur=rt;rt=ch[rt][1];
fa[rt]=0,clear(cur);return;
}
if(!ch[rt][1])
{
int cur=rt;rt=ch[rt][0];
fa[rt]=0,clear(cur);return;
}
int cur=rt,x=pre();
fa[ch[cur][1]]=x,ch[x][1]=ch[cur][1];
clear(cur),maintain(rt);
}
}t;
signed main()
{
read(n),read(m);
for(ri int i=1,x;i<=n;++i) read(x),t.ins(x);
for(ri int i=1,x,op;i<=m;++i)
{
read(op),read(x),x^=lst;
if(op==1) t.ins(x);
else if(op==2) t.del(x);
else if(op==3) lst=t.rk(x),ans^=lst;
else if(op==4) lst=t.kth(x),ans^=lst;
else if(op==5) t.ins(x),t.pre(),lst=val[rt],ans^=lst,t.del(x);
else t.ins(x),t.nxt(),lst=val[rt],ans^=lst,t.del(x);
}
wt(ans);
return 0;
}
\(upd11.9\):才发现自己快写居然是\(int\)……
一些例题
- T1 P2343 宝石管理系统
虽然他是蓝题,但是他比下一题还裸
点击查看代码
#include<bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
mt19937 srd(time(0));
cs int N=5e5+3,inf=1e18;
int n,cnt,rt,q;
il int Z(cs int x){return x>0?x:-x;}
struct Treap{int son[2],cnt,size,rnd,val;}t[N];
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) pc('-'),x=-x;if(x>9) wt(x/10);pc(x%10|48);}
il void upd(cs int x){t[x].size=t[x].cnt+t[t[x].son[1]].size+t[t[x].son[0]].size;}
il void rotate(int &x,cs int dir)
{
int s=t[x].son[dir];
t[x].son[dir]=t[s].son[dir^1],
t[s].son[dir^1]=x,upd(x),upd(s),x=s;
}
void insert(int &x,cs int val)
{
if(!x)
return x=++cnt,t[x].rnd=srd(),
t[x].size=t[x].cnt=1,t[x].val=val,void();
t[x].size++;
if(t[x].val==val) return t[x].cnt++,void();
int dir=t[x].val<val; insert(t[x].son[dir],val);
if(t[x].rnd>t[t[x].son[dir]].rnd) rotate(x,dir);
upd(x);
}
int kth(cs int x,cs int k)
{
if(!x) return 0;
if(k<=t[t[x].son[1]].size) return kth(t[x].son[1],k);
if(k<=t[t[x].son[1]].size+t[x].cnt) return t[x].val;
return kth(t[x].son[0],k-t[x].cnt-t[t[x].son[1]].size);
}
signed main()
{
read(n),read(q);
for(ri int i=1,x;i<=n;++i) read(x),insert(rt,x);
for(ri int i=1,x,c;i<=q;++i)
{
read(c),read(x);
if(c==1) wt(kth(rt,x)),pc('\n');
else insert(rt,x);
}
}
- T2 P2234 [HNOI2002]营业额统计
找前驱后继就行,甚至不用删除,就是找的时候注意下可以相等就行(不过好像可以用\(STL\)水过去
点击查看代码
#include<bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
mt19937 srd(time(0));
cs int N=4e4+3,inf=1e9;
int n,cnt,ans,rt,o;
il int Z(cs int x){return x>0?x:-x;}
struct Treap{int son[2],cnt,size,rnd,val;}t[N];
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) pc('-'),x=-x;if(x>9) wt(x/10);pc(x%10|48);}
il void upd(cs int x){t[x].size=t[x].cnt+t[t[x].son[1]].size+t[t[x].son[0]].size;}
il void rotate(int &x,cs int dir)
{
int s=t[x].son[dir];
t[x].son[dir]=t[s].son[dir^1],
t[s].son[dir^1]=x,upd(x),upd(s),x=s;
}
void insert(int &x,cs int val)
{
if(!x)
return x=++cnt,t[x].rnd=srd(),
t[x].size=t[x].cnt=1,t[x].val=val,void();
t[x].size++;
if(t[x].val==val) return t[x].cnt++,void();
int dir=t[x].val<val; insert(t[x].son[dir],val);
if(t[x].rnd>t[t[x].son[dir]].rnd) rotate(x,dir);
upd(x);
}
int pre(cs int x,cs int val)
{
if(!x) return -inf;
if(t[x].val>val) return pre(t[x].son[0],val);//可以是相等的数
return max(t[x].val,pre(t[x].son[1],val));
}
int nxt(cs int x,cs int val)
{
if(!x) return inf;
if(t[x].val<val) return nxt(t[x].son[1],val);//可以是相等的数
return min(t[x].val,nxt(t[x].son[0],val));
}
signed main()
{
read(n),read(o),insert(rt,o),ans=o;
for(ri int i=2,x,a,b;i<=n;++i)
read(x),a=pre(rt,x),b=nxt(rt,x),
insert(rt,x),ans+=min(x-a,b-x);//后插入,以免查到自己
wt(ans);
}
- T3 P2073 送花
直接粘板子见祖宗
对于最大值可以找最右边,最小值可以找最左边,最后递归一加就行(那你为什么调那么久
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
mt19937 srd(time(0));
cs int N=1e6+3+1e5,inf=1e9;
int n,cnt,rt;
struct Treap{int son[2],cnt,size,val,rnd,bea;}t[N];
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) pc('-'),x=-x;if(x>9) wt(x/10);pc(x%10|48);}
il void upd(cs int x)
{
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+t[x].cnt;
}
il void rotate(int &x,cs int dir)
{
int s=t[x].son[dir];
t[x].son[dir]=t[s].son[dir^1],
t[s].son[dir^1]=x,upd(x),upd(s),x=s;
}
void insert(int &x,cs int val,cs int bea)
{
if(!x)
return x=++cnt,t[x].rnd=srd(),t[x].bea=bea,
t[x].val=val,t[x].cnt=t[x].size=1,void();
t[x].size++;
if(t[x].val==val) return;
int dir=t[x].val<val; insert(t[x].son[dir],val,bea);
if(t[t[x].son[dir]].rnd<t[x].rnd) rotate(x,dir);
upd(x);
}
void delet(int &x,cs int val)
{
if(!x) return;
if(t[x].val==val)
{
bool dir=t[t[x].son[0]].rnd>t[t[x].son[1]].rnd;
if(t[x].son[0]==0||t[x].son[1]==0) x=t[x].son[0]+t[x].son[1];
else rotate(x,dir),delet(x,val);return;
}
t[x].size--,delet(t[x].son[t[x].val<val],val);
upd(x);
}
int find(cs int f)
{
int x=rt;
if(f) while(t[x].son[0]) x=t[x].son[0];//Min1
else while(t[x].son[1]) x=t[x].son[1];//Max0
return x;
}
int calc(cs int x,cs bool f)//1val 0bea
{
if(!x) return 0;
return f?(calc(t[x].son[0],f)+t[x].val+calc(t[x].son[1],f)):
(calc(t[x].son[0],f)+t[x].bea+calc(t[x].son[1],f));
}
signed main()
{
// freopen("P2073_2.in","r",stdin);
// freopen("1.out","w",stdout);
while(1)
{
int opt,x,c,o;
read(opt);
if(opt==-1) break;
if(opt==1) read(x),read(c),insert(rt,c,x);
else if(opt==2) o=find(0),delet(rt,t[o].val);
else if(opt==3) o=find(1),delet(rt,t[o].val);
}
wt(calc(rt,0)),pc(' '),wt(calc(rt,1));
return 0;
}
需要转化的题。注意一下查询是求第\(k\)大不是第\(k\)小,然后踢人就是不停找前驱,插入的时候由于之前的\(\Delta\)对他没有影响,所以把这个数减去\(\Delta\)再加进去就行了
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
#define int long long
using namespace std;
mt19937 srd(time(0));
cs int N=1e6+3,inf=1e18;
int n,cnt,rt,Min,delta,s,re;
struct Treap{int val,cnt,rnd,son[2],size;}t[N];
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0) pc('-'),x=-x;if(x>9) wt(x/10);pc(x%10|48);}
il void upd(cs int x){t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+t[x].cnt;}
il void rotate(int &rt,cs int dir)
{
int s=t[rt].son[dir];
t[rt].son[dir]=t[s].son[dir^1],
t[s].son[dir^1]=rt,upd(rt),upd(s),rt=s;
}
void insert(int &x,cs int val)
{
if(!x)
return x=++cnt,t[x].rnd=srd(),
t[x].val=val,t[x].cnt=t[x].size=1,void();
t[x].size++;
if(t[x].val==val) return t[x].cnt++,void();
int dir=t[x].val<val; insert(t[x].son[dir],val);
if(t[t[x].son[dir]].rnd<t[x].rnd) rotate(x,dir);
upd(x);
}
void delet(int &x,cs int val)
{
if(!x) return;
if(t[x].val==val)
{
if(t[x].cnt>1) return t[x].cnt--,t[x].size--,void();
bool dir=t[t[x].son[0]].rnd>t[t[x].son[1]].rnd;
if(t[x].son[0]==0||t[x].son[1]==0) x=t[x].son[0]+t[x].son[1];
else rotate(x,dir),delet(x,val);
}
else t[x].size--,delet(t[x].son[t[x].val<val],val);
upd(x);//2
}
int kth(cs int x,cs int k)//第k大
{
if(!x) return 0;
if(t[t[x].son[1]].size>=k) return kth(t[x].son[1],k);
if(t[t[x].son[1]].size+t[x].cnt>=k) return t[x].val;
return kth(t[x].son[0],k-t[x].cnt-t[t[x].son[1]].size);
}
int pre(cs int x,cs int val)
{
if(!x) return -inf;
if(t[x].val>val) return pre(t[x].son[0],val);
return max(pre(t[x].son[1],val),t[x].val);
}
signed main()
{
// freopen("unhappy.in","r",stdin);
// freopen("unhappy.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n>>Min;
for(ri int i=1,tmp,o,u;i<=n;++i)
{
char opt;int x;
cin>>opt>>x;
if(opt=='I')
if(x-delta>=Min) insert(rt,x-delta),re++,s++;
if(opt=='A') Min-=x,delta+=x;
if(opt=='S')
{
Min+=x,delta-=x,tmp=Min-1;
while(o=pre(rt,tmp),o!=-inf)
delet(rt,o),tmp=o,re--;
}
if(opt=='F')
if(re<x) cout<<-1<<'\n';
else cout<<kth(rt,x)+delta<<'\n'; //第k小 re-x+1
}
cout<<s-re;
return 0;
}
- T5 P1503 鬼子进村
又是可以用\(STL\)水过去的那种题
村庄是一条链,把炸毁的点的丢进去,然后对于每一个询问\(x\),找到它的前驱\(a\),即在\(x\)往前走第一个被堵到的地方是\(a\),然后再找\(x\)的后继\(b\),即在\(x\)往后走第一个被堵到的地方是\(b\),所以\((a,b)\)就是这个士兵可以到的区间
\(Tips:\)注意边界!!(也有可能是只有我的写法需要注意)\(a\ge0,b\le n+1\)以及
若士兵被围堵在摧毁了的房子中,那只能等死了。。。。。。
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define ri register
#define pc(i) putchar(i)
using namespace std;
cs int N=1e6+3,inf=1e9+7;
mt19937 srd(time(0));
struct Treap{int cnt,son[2],rnd,val,size;}t[N];
namespace zxy{
il void read(int &as)
{
as=0;int f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') as=(as<<3)+(as<<1)+(ch^48),ch=getchar();as*=f;
}
void wt(int x){if(x<0)x=-x,pc('-');if(x>9) wt(x/10);pc(x%10|48);}
}using namespace zxy;
int cnt,rt;
il void Update(cs int x){t[x].size=t[x].cnt+t[t[x].son[1]].size+t[t[x].son[0]].size;}
il void Rotate(int &x,cs int dir)
{
int s=t[x].son[dir];
t[x].son[dir]=t[s].son[dir^1],
t[s].son[dir^1]=x,Update(x),Update(s),x=s;
}
void Insert(int &x,cs int val)
{
if(!x)
return x=++cnt,t[x].val=val,
t[x].rnd=srd(),t[x].size=t[x].cnt=1,void();
++t[x].size;
if(t[x].val==val) return t[x].cnt++,void();
int dir=t[x].val<val;Insert(t[x].son[dir],val);
if(t[x].rnd>t[t[x].son[dir]].rnd) Rotate(x,dir);
Update(x);
}
void Delete(int &x,cs int val)
{
if(!x) return;
if(t[x].val==val)
{
if(t[x].cnt>1) return t[x].cnt--,t[x].size--,void();
int dir=t[t[x].son[0]].rnd>t[t[x].son[1]].rnd;
if(t[x].son[0]==0||t[x].son[1]==0) x=t[x].son[0]+t[x].son[1];
else Rotate(x,dir),Delete(x,val);
}
else t[x].size--,Delete(t[x].son[t[x].val<val],val);
Update(x);
}
bool hs[N];
int n,m,sta[N],top;
int pre(cs int x,cs int val)
{
if(!x) return 0;
if(t[x].val>=val) return pre(t[x].son[0],val);
return max(pre(t[x].son[1],val),t[x].val);
}
int nxt(cs int x,cs int val)
{
if(!x) return n+1;
if(t[x].val<=val) return nxt(t[x].son[1],val);
return min(t[x].val,nxt(t[x].son[0],val));
}
signed main()
{
read(n),read(m);
for(ri int i=1;i<=m;++i)
{
char op;int x;cin>>op;
if(op=='D') read(x),hs[x]=1,sta[++top]=x,Insert(rt,x);
else if(op=='R') hs[sta[top]]=0,Delete(rt,sta[top--]);
else read(x),wt(hs[x]?0:(nxt(rt,x)-pre(rt,x)-1)),pc('\n');
}
}
可持久化 \(\operatorname{fhq-Treap}\)
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define LL long long
#define pc(i) putchar(i)
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k) for(int i=(j);(i)>=(k);--(i))
using namespace std;
mt19937 srd(time(0));
cs LL inf=1e18+7,N=5e5+7;
LL FL,CH;
template<typename T> bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
LL in(T&a,Args&...args){return in(a)+in(args...);}
void wt(LL x){if(x<0)x=-x,pc('-');if(x>9)wt(x/10);pc(x%10|48);}
int n,cnt,ro[N];
namespace Treap
{
#define ls(i) (t[i].son[0])
#define rs(i) (t[i].son[1])
struct fhq{int son[2],sz,rnd;LL val;}t[N*50]; int cnt=0; //<<5 -> *50
il void pushup(cs int x){ t[x].sz=t[ls(x)].sz+t[rs(x)].sz+1; }
il int newnode(cs LL val){ return t[++cnt].val=val,t[cnt].rnd=srd(),t[cnt].sz=1,cnt; }
int merge(cs int x,cs int y)
{
if(!x||!y) return x+y; int rt=++cnt;
if(t[x].rnd<=t[y].rnd) return t[rt]=t[x],rs(rt)=merge(rs(rt),y),pushup(rt),rt;
else return t[rt]=t[y],ls(rt)=merge(x,ls(rt)),pushup(rt),rt;
}
void split(cs int cur,cs LL k,int &x,int &y)
{
if(!cur) return x=y=0,void();
if(t[cur].val<=k) x=++cnt,t[x]=t[cur],split(rs(x),k,rs(x),y),pushup(x);
else y=++cnt,t[y]=t[cur],split(ls(y),k,x,ls(y)),pushup(y);
}
il int kth(int x,LL k)
{
while(1)
if(k<=t[ls(x)].sz) x=ls(x);
else if(k==t[ls(x)].sz+1) return x;
else k-=t[ls(x)].sz+1,x=rs(x);
}
}using namespace Treap;
signed main()
{
in(n); fo(i,1,n)/*1.插入 2.删除 3.排名 4.kth 5.前驱 6.后继*/
{
int x,y,a,z,pre,op; in(pre,op,a),ro[i]=ro[pre];
if(op==1) split(ro[i],a,x,y),ro[i]=merge(merge(x,newnode(a)),y);
else if(op==2) split(ro[i],a,x,z),split(x,a-1,x,y),y=merge(ls(y),rs(y)),ro[i]=merge(merge(x,y),z);
else if(op==3) split(ro[i],a-1,x,y),wt(t[x].sz+1),pc('\n'),ro[i]=merge(x,y);
else if(op==4) wt(t[kth(ro[i],a)].val),pc('\n');
else if(op==5) split(ro[i],a-1,x,y),wt(x?t[kth(x,t[x].sz)].val:-2147483647),pc('\n'),ro[i]=merge(x,y);
else split(ro[i],a,x,y),wt(y?t[kth(y,1)].val:2147483647),pc('\n'),ro[i]=merge(x,y);
}
return 0;
}
文艺平衡树
点击查看代码
#include<bits/stdc++.h>
#define cs const
#define il inline
#define LL long long
#define pc(i) putchar(i)
#define fo(i,j,k) for(int i=(j);(i)<=(k);++(i))
#define of(i,j,k) for(int i=(j);(i)>=(k);--(i))
using namespace std;
mt19937 srd(time(0));
cs int inf=0x3f3f3f3f,Mod=998244353,N=2e5+7;
int FL,CH;
template<typename T> bool in(T&a)
{
for(FL=1;!isdigit(CH)&&CH!=EOF;CH=getchar())
if(CH=='-')FL=-1;
for(a=0;isdigit(CH);CH=getchar())
a=a*10+CH-'0';
return a*=FL,CH==EOF?0:1;
}
template<typename T,typename...Args>
int in(T&a,Args&...args){return in(a)+in(args...);}
void wt(int x){if(x<0)x=-x,pc('-');if(x>9)wt(x/10);pc(x%10|48);}
int root,n,m,L,R;
namespace Treap
{
#define ls(i) (t[i].son[0])
#define rs(i) (t[i].son[1])
struct fhq{int son[2],sz,val,rnd,lz;}t[N]; int cnt=0;
int newnode(cs int w){ return t[++cnt].val=w,t[cnt].sz=1,t[cnt].rnd=srd(),cnt; }
il void pushup(cs int x){ t[x].sz=t[ls(x)].sz+t[rs(x)].sz+1; }
il void pushdown(cs int x)
{ if(t[x].lz) swap(ls(x),rs(x)),t[ls(x)].lz^=1,t[rs(x)].lz^=1,t[x].lz=0; }
void split(cs int cur,cs int sz,int &x,int &y)//split by sz
{
if(!cur) return x=y=0,void(); pushdown(cur);
if(t[ls(cur)].sz+1<=sz)
return x=cur,split(rs(cur),sz-t[ls(cur)].sz-1,rs(cur),y),pushup(cur),void();
else return y=cur,split(ls(cur),sz,x,ls(cur)),pushup(cur),void();
}
int merge(cs int x,cs int y)
{
if(!x||!y) return x+y;
if(t[x].rnd>=t[y].rnd) return pushdown(x),rs(x)=merge(rs(x),y),pushup(x),x;
else return pushdown(y),ls(y)=merge(x,ls(y)),pushup(y),y;
}
void reverse(cs int l,cs int r)
{
int x,y,z;
split(root,l-1,x,y),split(y,r-l+1,y,z),
t[y].lz^=1,root=merge(merge(x,y),z);
}
void print(cs int x)
{
if(!x) return;
pushdown(x),print(ls(x)),
wt(t[x].val),pc(' '),print(rs(x));
}
}using namespace Treap;
signed main()
{
in(n,m); fo(i,1,n) root=merge(root,newnode(i));
while(m--) in(L,R),reverse(L,R); print(root);
return 0;
}
附点模板数据
点击查看data1
50
1 577793
1 408221
1 880861
2 408221
1 460353
1 223489
6 577713
4 2
5 889905
2 880861
1 100033
1 73956
1 22575
5 583761
6 571549
1 812645
4 3
1 643621
1 451623
6 14895
1 556691
4 1
1 225789
2 22575
1 632329
3 73956
1 316785
5 101413
4 11
5 639414
6 636353
1 272382
1 434049
2 643621
1 99617
2 577793
1 921581
1 894033
3 223489
1 767367
3 272382
1 642721
1 272033
3 632329
1 737721
1 864513
5 746457
1 877545
1 51097
1 484817
577793
460353
880861
577793
577793
100033
22575
22575
1
100033
643621
632329
643621
4
6
13
737721
点击查看data2
20
1 964673
5 968705
4 1
3 964673
5 965257
1 915269
1 53283
3 964673
3 53283
3 53283
1 162641
5 973984
1 948119
2 915269
2 53283
6 959161
1 531821
1 967521
2 531821
1 343410
964673
964673
1
964673
3
1
1
964673
964673
文章内容参考:https://oiwiki.org/ds/splay/
但是图片都是窝按自己理解画\(der\)

浙公网安备 33010602011771号