平衡树

\(\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}\) 步骤有三种,具体分为六种情况:

  1. \(zig\)操作:\(p\)为根(最后一步)
  2. \(zig-zag\)操作:\(p\)非根,\(x,p\)为同侧子节点
  3. \(zig-zag\)操作:\(p\)非根,\(x,p\)为异侧子节点

插入

  1. 如果树空了,则直接插入根并退出。
  2. 如果当前节点的权值等于 \(k\) 则增加当前节点的大小并更新节点和父亲的信息,将当前节点进行 \(\operatorname{Splay}\) 操作。
  3. 否则按照二叉查找树的性质向下找,找到空节点就插入即可
    注意最后需要进行 \(\operatorname{Splay}\) 操作。

查询 \(x\) 的排名

根据二叉查找树的定义和性质

  1. 如果 \(x\) 比当前节点的权值小,向其左子树查找。
  2. 如果 \(x\) 比当前节点的权值大,将答案加上左子树(\(size\))和当前节点(\(cnt\))的大小,向其右子树查找。
  3. 如果 \(x\) 与当前节点的权值相同,将答案加 \(1\) 并返回。

查询\(x\)的前驱

可以转化为:将 \(x\) 插入(此时 \(x\) 已经在根的位置了),前驱即为 \(x\) 的左子树中最右边的节点,最后将 \(x\) 删除即可。
注意最后需要进行 \(\operatorname{Splay}\) 操作。

查询\(x\)的后继

可以转化为:将 \(x\) 插入(此时 \(x\) 已经在根的位置了),后继即为 \(x\) 的右子树中最左边的节点,最后将 \(x\) 删除即可。
注意最后需要进行 \(\operatorname{Splay}\) 操作。

合并两棵树

合并两棵 \(\operatorname{Splay}\) 树,设两棵树的根节点分别为 \(x\)\(y\),那么我们要求 \(x\) 树中的最大值小于 \(y\) 树中的最小值。合并操作如下:

  1. 如果 \(x\)\(y\) 其中之一或两者都为空树,直接返回不为空的那一棵树的根节点或空树。
  2. 否则将 \(x\) 树中的最大值 $$\operatorname{Splay}$$ 到根,然后把它的右子树设置为 y 并更新节点的信息,然后返回这个节点。

删除

首先将 \(x\) 旋转到根的位置。(通过rk()即可)

  1. 如果 \(cnt[x]>1\)(有不止一个 \(x\)),那么将 \(cnt[x]\)\(1\) 并退出。
  2. 否则,合并它的左右两棵子树即可。

P3369 【模板】普通平衡树

$\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;
}

P6136 【模板】普通平衡树(数据加强版)

$\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\)……

一些例题

点击查看代码
#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);
	}
} 
点击查看代码
#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}\)

luogu 3835

点击查看代码
#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;
}

文艺平衡树

luogu P3391

点击查看代码
#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\)

posted @ 2022-11-04 22:03  Bertidurlah  阅读(47)  评论(0)    收藏  举报