【模板】splay

转自大佬博客
天晓得我这个星际玩家有没有把哪里抄错

//splay
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define re register
#define Key_value ch[ch[rt][1]][0]
const int N=5e5+10;
const int INF=0x3f3f3f3f;
namespace IO{	
    template<class T>inline void read(T&s)
    {
	    re int f=0;re char ch=getchar();s=0;
	    while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
	    while(ch>='0'||ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	    f?s=-s:s=s;
    }
    template<class M>inline void write(M s)
    {
    	static int buf[40];re int p=0;
    	if(s<0)putchar('-'),s=-s;
    	do{
    		buf[p++]=s%10;s/=10;
		}while(s);
		for(re int i=p-1;i>=0;i--)putchar(buf[i]+48);
	    putchar('\n');
	}
}
int pre[N],ch[N][2],key[N],sz[N];
int sum[N],rev[N],same[N];
int lx[N],rx[N],mx[N];
int rt,tot1,a[N],n,q;
int s[N],tot2;//内存池和容量
struct SPLAY{
	inline void Newnode(int &r,int fa,int k)//新建节点 
	{
		if(tot2)r=s[tot2--];//取的时候是tot2--,存的时候就是++tot2
		else r=++tot1;
		pre[r]=fa;
		ch[r][0]=ch[r][1]=0;
		key[r]=k;
		sum[r]=k;
		rev[r]=same[r]=0;
		lx[r]=rx[r]=mx[r]=k;
		sz[r]=1;
		return; 
	}
	inline void push_up(int r)
	{
		re int lson=ch[r][0],rson=ch[r][1];
	    sz[r]=sz[lson]+sz[rson]+1;
	    sum[r]=sum[lson]+sum[rson]+key[r];
	    lx[r]=max(lx[lson],sum[lson]+key[r]+max(0,lx[rson]));
	    rx[r]=max(rx[rson],sum[rson]+key[r]+max(0,rx[lson]));
	    mx[r]=max(0,rx[lson])+key[r]+max(0,lx[rson]);
	    return;
	}
	inline void Build(int &x,int l,int r,int fa)
	{
		if(l>r)return;
		re int mid=l+r>>1;
		Newnode(x,fa,a[mid]);
		Build(ch[x][0],l,mid-1,x);
		Build(ch[x][1],mid+1,r,x);
		push_up(x);
		return;
	}
	inline void Init()
	{
		rt=tot1=tot2=0;
		ch[rt][0]=ch[rt][1]=sz[rt]=pre[rt]=0;
		same[rt]=rev[rt]=sum[rt]=key[rt]=0;
		lx[rt]=rx[rt]=mx[rt]=-INF;
		Newnode(rt,0,-1);
		Newnode(ch[rt][1],rt,-1);
		for(re int i=0;i<n;i++)
		    IO::read(a[i]);
		Build(Key_value,0,n-1,ch[rt][1]);
		push_up(ch[rt][1]);
		push_up(rt);
	}
	//更新翻转 
	inline void Update_Rev(int r)
	{
		if(!r)return;
		swap(ch[r][0],ch[r][1]);
		swap(lx[r],rx[r]);
		rev[r]^=1;
		return;
	}
	inline void Update_Same(int r,int v)
	{
		if(!r)return;
		key[r]=v;
		sum[r]=v*sz[r];
		lx[r]=rx[r]=mx[r]=max(v,v*sz[r]);
		same[r]=1;
		return;
	}
	inline void push_down(int r)
	{
		if(same[r])
		{
			Update_Same(ch[r][0],key[r]);
			Update_Same(ch[r][1],key[r]);
			same[r]=0;
		}
		if(rev[r])
		{
			Update_Rev(ch[r][0]);
			Update_Rev(ch[r][1]);
			rev[r]=0;
		}
		return;
	}
	//查找第k大 
	inline int Get_kth(int r,int k)
	{
		push_down(r);
		re int t=sz[ch[r][0]]+1;
		if(t==k)return r;
		if(t>k)return Get_kth(ch[r][0],k);
		else return Get_kth(ch[r][1],k-t);
	}
	//旋转,0为左旋,1为右旋 
	inline void Rotate(int x,int kind)
	{
		re int y=pre[x];
		push_down(y);
		push_down(x);
		ch[y][!kind]=ch[x][kind];
		pre[ch[x][kind]]=y;
		if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;
		pre[x]=pre[y];
		ch[x][kind]=y;
		pre[y]=x;
		push_up(y);
	}
	//Splay调整,将r结点调整到goal下面 
	inline void Splay(int r,int goal)
	{
		push_down(r);
		while(pre[r]!=goal)
		{
			if(pre[pre[r]]==goal)
			{
				push_down(pre[r]);
				push_down(r);
				Rotate(r,ch[pre[r]][0]==r);
			}
			else
			{
				push_down(pre[pre[r]]);
				push_down(pre[r]);
				push_down(r);
				re int y=pre[r];
				re int kind=ch[pre[y]][0]==y;
				if(ch[y][kind]==r)
				{
					Rotate(r,!kind);
					Rotate(r,kind);
				}
				else
				{
					Rotate(y,kind);
					Rotate(r,kind);
				}
			}
		}
		push_up(r);
		if(goal==0)rt=r;
		return;
	}
	//在第pos个数后面插入tot个数 
	inline void Insert(int pos,int tot)
	{
		for(re int i=0;i<tot;i++)
		    IO::read(a[i]);
		Splay(Get_kth(rt,pos+1),0);
		Splay(Get_kth(rt,pos+2),rt);
		Build(Key_value,0,tot-1,ch[rt][1]);
		push_up(ch[rt][1]);
		push_up(rt);
		return;
	}
	//删除子树 
	inline void Erase(int r)
	{
		if(!r)return;
		s[++tot2]=r;
		Erase(ch[r][0]);
		Erase(ch[r][1]);
		return;
	}
	//从第pos个数开始连续删除tot个数 
	inline void Delete(int pos,int tot)
	{
		Splay(Get_kth(rt,pos),0);
		Splay(Get_kth(rt,pos+tot+1),rt);
		Erase(Key_value);
		pre[Key_value]=0;
		Key_value=0;
		push_up(ch[rt][1]);
		push_up(rt);
		return;
	}
	//将从第pos个数开始的连续的tot个数修改为c 
	inline void Make_Same(int pos,int tot,int c)
	{
		Splay(Get_kth(rt,pos),0);
		Splay(Get_kth(rt,pos+tot+1),rt);
		Update_Same(Key_value,c);
		push_up(ch[rt][1]);
		push_up(rt);
		return;
	}
	//将第pos个数开始的连续tot个数进行反转 
	inline void Reverse(int pos,int tot)
	{
		Splay(Get_kth(rt,pos),0);
		Splay(Get_kth(rt,pos+tot+1),rt);
		Update_Rev(Key_value);
		push_up(ch[rt][1]);
		push_up(rt);
		return;
	}
	inline int Get_Sum(int pos,int tot)
	{
		Splay(Get_kth(rt,pos),0);
		Splay(Get_kth(rt,pos+tot+1),rt);
		return sum[Key_value];
	}
	inline int Get_MaxSum(int pos,int tot)
	{
		Splay(Get_kth(rt,pos),0);
		Splay(Get_kth(rt,pos+tot+1),rt);
		return mx[Key_value];
	}
	inline void solve()
	{
		using namespace IO;
		read(n);read(q);Init();
		re char op[20];
		re int x,y,z;
		while(q--)
		{
			scanf("%s",op);
            if(strcmp(op,"INSERT")==0)
            	read(x),read(y),Insert(x,y);
            else if(strcmp(op,"DELETE")==0)
                read(x),read(y),Delete(x,y);
            else if(strcmp(op,"MAKE-SAME")==0)
                read(x),read(y),read(z),Make_Same(x,y,z);
		    else if(strcmp(op,"REVERSE")==0)
		        read(x),read(y),Reverse(x,y);
		    else if(strcmp(op,"GET-SUM")==0)
		        read(x),read(y),write(Get_Sum(x,y));
		    else if(strcmp(op,"MAX-SUM")==0)
		        write(Get_MaxSum(1,sz[rt]-2));
		}
		return;
	}
}splay;
int main()
{
	splay.solve();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值