记录编号 575061 评测结果 AAAAAAAAAA
题目名称 [TYVJ1730]二逼平衡树 最终得分 100
用户昵称 Gravatar瑆の時間~無盡輪迴·林蔭 是否通过 通过
代码语言 C++ 运行时间 3.477 s
提交时间 2022-09-02 11:54:55 内存使用 124.18 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
using namespace std;
const int N=50001,LOG=20;
struct PE
{
	int val,size,cnt,ch[2],ff;
	PE()
	{
		val=0;
		size=0;
		cnt=0;
		ch[0]=0;
		ch[1]=0;
		ff=0;
	};
};
PE t[N*LOG*5];
int RT[N*LOG],tot=0,VAL[N],n,m;
int ls(int x)
{
	return t[x].ch[0];
}
int rs(int x)
{
	return t[x].ch[1];
}
void pushup(int x)
{
	t[x].size=t[x].cnt+t[ls(x)].size+t[rs(x)].size;
}
void rotate(int x)
{
	int y=t[x].ff;
	int z=t[y].ff;
	int k=(t[y].ch[1]==x);
	t[z].ch[t[z].ch[1]==y]=x;
	t[y].ch[k]=t[x].ch[k^1];
	t[t[x].ch[k^1]].ff=y;
	t[x].ch[k^1]=y;
	t[y].ff=x;
	t[x].ff=z;
	pushup(y);
	pushup(x);
}
void Splay(int x,int goal,int IDX)
{
	while(t[x].ff!=goal)
	{
		int y=t[x].ff;
		int z=t[y].ff;
		if(z!=goal)
		{
			(t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y);
		}
		rotate(x);
	}
	if(goal==0)
	{
		RT[IDX]=x;
	}
}
void Insert(int x,int IDX)
{
	int u=RT[IDX],ff=0;
	if(!u)
	{
		u=++tot;
		t[u].ch[0]=0;
		t[u].ch[1]=0;
		t[u].val=x;
		t[u].cnt=1;
		t[u].size=1;
		RT[IDX]=u;
		return;
	}
	while(u&&t[u].val!=x)
	{
		ff=u;
		u=t[u].ch[t[u].val<x];
	}
	if(t[u].val==x&&u)
	{
		t[u].cnt++;
	}
	else
	{
		u=++tot;
		t[u].val=x;
		t[u].ch[0]=0;
		t[u].ch[1]=0;
		t[u].cnt=1;
		t[u].size=1;
		t[u].ff=ff;
		if(ff)
		{
			t[ff].ch[t[ff].val<x]=u;
		} 
	}
	Splay(u,0,IDX);
}
void Find(int x,int IDX)
{
	int u=RT[IDX];
	while(t[u].ch[t[u].val<x]&&t[u].val!=x)
	{
		u=t[u].ch[t[u].val<x];
	}
	Splay(u,0,IDX);
}
int Next(int x,int F,int IDX)
{
	Find(x,IDX);
	int u=RT[IDX];
	if(t[u].val<x&&!F)
		return u;
	if(t[u].val>x&&F)
	{
		return u;
	} 
	u=t[u].ch[F];
	while(t[u].ch[F^1])
		u=t[u].ch[F^1];
	return u;
}
void Delete(int x,int IDX)
{
	int u=RT[IDX];
	int pre=Next(x,0,IDX);
	int nxt=Next(x,1,IDX);
	Splay(pre,0,IDX);
	Splay(nxt,pre,IDX);
	int del=t[nxt].ch[0];
	if(t[del].cnt>1)
	{
		t[del].cnt--;
		Splay(del,0,IDX);
	}
	else
	{
		t[nxt].ch[0]=0;
		return;
	}
}
void Build(int x,int l,int r)
{
	Insert(998244353,x);
	Insert(-998244353,x);
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	Build(x<<1,l,mid);
	Build(x<<1|1,mid+1,r); 
}
void Fir_Insert(int x,int l,int r,int k,int s)
{
	Insert(s,x);
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	if(k<=mid)
		Fir_Insert(x<<1,l,mid,k,s);
	else
		Fir_Insert(x<<1|1,mid+1,r,k,s);
}
void Fir_Delete(int x,int l,int r,int k,int s)
{
	Delete(s,x);
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	if(k<=mid)
		Fir_Delete(x<<1,l,mid,k,s);
	else
		Fir_Delete(x<<1|1,mid+1,r,k,s); 
}
void CHANGE(int pos,int s)
{
	Fir_Delete(1,1,n,pos,VAL[pos]);
	VAL[pos]=s;
	Fir_Insert(1,1,n,pos,VAL[pos]);
}
int Fir_Rank(int x,int l,int r,int nl,int nr,int k)
{
	//RANK算出的并不是该数排名,而是比这个数字小的数的个数 
	if(nl<=l&&nr>=r)
	{
		Find(k,x);
		int u=RT[x];
		if(t[u].val>=k)
		{
			return t[ls(u)].size-1;//开始插入了冗余量 
		}
		else
		{
			return t[ls(u)].size+t[u].cnt-1;
		}
	}
	int mid=(l+r)>>1,ans=0;
	if(nl<=mid)
	{
		ans+=Fir_Rank(x<<1,l,mid,nl,nr,k);
	}
	if(nr>mid)
		ans+=Fir_Rank(x<<1|1,mid+1,r,nl,nr,k);
	return ans;
}
int Fir_Front(int x,int l,int r,int nl,int nr,int k)
{
	if(nl<=l&&nr>=r)
	{
		return t[Next(k,0,x)].val;
	}
	int mid=(l+r)>>1,res=-998244353;
	if(nl<=mid)
		res=max(res,Fir_Front(x<<1,l,mid,nl,nr,k));
	if(nr>mid)
		res=max(res,Fir_Front(x<<1|1,mid+1,r,nl,nr,k));
	return res;
}
int Fir_Back(int x,int l,int r,int nl,int nr,int k)
{
	if(nl<=l&&nr>=r)
	{
		return t[Next(k,1,x)].val;
	}
	int mid=(l+r)>>1,res=998244353;
	if(nl<=mid)
		res=min(res,Fir_Back(x<<1,l,mid,nl,nr,k));
	if(nr>mid)
		res=min(res,Fir_Back(x<<1|1,mid+1,r,nl,nr,k));
	return res;
}
int Fir_KTH(int nl,int nr,int k)
{
	int L=0,R=100000000,mid,Check,ans;
	while(L<=R)
	{
		mid=(L+R)>>1;
		Check=Fir_Rank(1,1,n,nl,nr,mid)+1;
		//Check实际上才是mid的排名 
		if(Check>k)
		{
			R=mid-1;
		}
		else
		{
			ans=mid;
			L=mid+1;
		}
	}
	return ans;
}
int main()
{
	freopen("psh.in","r",stdin);
	freopen("psh.out","w",stdout);
	scanf("%d%d",&n,&m);
	int a1,a2,a3,a4;
	Build(1,1,n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&VAL[i]);
		Fir_Insert(1,1,n,i,VAL[i]);
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a1,&a2,&a3);
		if(a1==1)
		{
			scanf("%d",&a4);
			printf("%d\n",Fir_Rank(1,1,n,a2,a3,a4)+1);
		}
		if(a1==2)
		{
			scanf("%d",&a4);
			printf("%d\n",Fir_KTH(a2,a3,a4));
		}
		if(a1==3)
		{
			CHANGE(a2,a3);
		}
		if(a1==4)
		{
			scanf("%d",&a4);
			printf("%d\n",Fir_Front(1,1,n,a2,a3,a4));
		}
		if(a1==5)
		{
			scanf("%d",&a4);
			printf("%d\n",Fir_Back(1,1,n,a2,a3,a4));
		}
	}
	return 0;
}