[Luogu 1533] 可怜的狗狗

<题目链接>

平衡树,我用的SBT。

排一下序尽量减少操作次数。

第K大询问。

以及插入删除。

#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=300010,MAXM=50010;
int n,m,x,y,a[MAXN],ans[MAXN];
struct Query
{
	int l,r,k,index;
	bool operator <(const Query &rhs) const
	{
		return l<rhs.l ? 1 : (l<rhs.l ? 0 : r<rhs.r);
	}
}q[MAXM];
class SBT
{
	public:
		int rt;
		SBT(void)
		{
			rt=cnt=0;
			memset(s,0,sizeof s);
		}
		void Insert(int &i,int x)
		{
			if(!i)
			{
				s[i=++cnt].v=x,s[i].size=1;
				return;
			}
			++s[i].size;
			bool t=x>s[i].v;
			Insert(s[i].c[t],x);
			Maintain(i,t);
		}
		void Erase(int &i,int x)
		{
			--s[i].size;
			if(x==s[i].v)
				if(s[i].c[0] && s[i].c[1])
				{
					int t=s[i].c[1];
					while(s[t].c[0])
						t=s[t].c[0];
					s[i].v=s[t].v;
					Erase(s[i].c[1],s[t].v);
				}
				else
					i=s[i].c[0] | s[i].c[1];
			else
				Erase(s[i].c[x>s[i].v],x);
		}
		int Xth(int i,int x)
		{
			int t=s[s[i].c[0]].size+1;
			if(x<t)
				return Xth(s[i].c[0],x);
			else if(x>t)
				return Xth(s[i].c[1],x-t);
			else
				return s[i].v;
		}
	private:
		int cnt;
		struct node
		{
			int v,size,c[2];
		}s[MAXN];
		void Update(int i)
		{
			s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1;
		}
		void Rotate(int &i,bool p)
		{
			int t=s[i].c[!p];
			s[i].c[!p]=s[t].c[p],s[t].c[p]=i;
			Update(i),Update(i=t);
		}
		void Maintain(int &i,bool p)
		{
			int t=s[s[i].c[!p]].size;
			if(t<s[s[s[i].c[p]].c[p]].size)
				Rotate(i,!p);
			else if(t<s[s[s[i].c[p]].c[!p]].size)
				Rotate(s[i].c[p],p),Rotate(i,!p);
			else
				return;
			Maintain(s[i].c[0],0);
			Maintain(s[i].c[1],1);
			Maintain(i,0);
			Maintain(i,1);
		}
}T;
int main(int argc,char *argv[])
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	for(int i=1;i<=m;++i)
	{
		scanf("%d %d %d",&q[i].l,&q[i].r,&q[i].k);
		q[i].index=i;
	}
	sort(q+1,q+m+1);
	x=1;
	for(int i=1,&rt=T.rt;i<=m;++i)
	{
		while(y<q[i].r)
			T.Insert(rt,a[++y]);
		while(x<q[i].l)
			T.Erase(rt,a[x++]);
		ans[q[i].index]=T.Xth(rt,q[i].k);
	}
	for(int i=1;i<=m;++i)
		printf("%d\n",ans[i]);
	return 0;
}
posted @ 2017-12-28 10:19  Capella  阅读(273)  评论(0编辑  收藏  举报

谢谢光临