【题解】Luogu P1533 可怜的狗狗

原题传送门

莫队介绍,Splay介绍

离线的题目,莫队是不错的解决方法

先把询问排一下序

剩下就套一个莫队的板子

每来一只狗就把漂亮值插入平衡树

每去掉一只狗就把漂亮值从平衡树中删掉

每次查询查平衡树中第k小

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define N 800005
#define M 50005
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf; 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
}
inline int read()
{
    register int x=0,f=1;register char ch=nc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=nc();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
struct Splay{
	int v,fa,ch[2],sum,rec;
}tree[N];
int tot=0;
inline void update(register int x)
{
	tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;
}
inline bool findd(register int x)
{
	return tree[tree[x].fa].ch[0]==x?0:1;
}
inline void connect(register int x,register int fa,register int son)
{
	tree[x].fa=fa;
	tree[fa].ch[son]=x;
} 
inline void rotate(register int x)
{
	int Y=tree[x].fa;
	int R=tree[Y].fa;
	int Yson=findd(x);
	int Rson=findd(Y);
	int B=tree[x].ch[Yson^1];
	connect(B,Y,Yson);
	connect(Y,x,Yson^1);
	connect(x,R,Rson);
	update(Y),update(x);
}
inline void splay(register int x,register int to)
{
	to=tree[to].fa;
	while(tree[x].fa!=to)
	{
		int y=tree[x].fa;
		if(tree[y].fa==to)
			rotate(x);
		else if(findd(x)==findd(y))
			rotate(y),rotate(x);
		else
			rotate(x),rotate(x);
	}	
}
inline int newpoint(register int v,register int fa)
{
	tree[++tot].fa=fa;
	tree[tot].v=v;
	tree[tot].sum=tree[tot].rec=1;
	return tot; 
}
inline void Insert(register int x)
{
	int now=tree[0].ch[1];
	if(tree[0].ch[1]==0)
	{
		newpoint(x,0);
		tree[0].ch[1]=tot;
	}
	else
	{
		while(19260817)
		{
			++tree[now].sum;
			if(tree[now].v==x)
			{
				++tree[now].rec;
				splay(now,tree[0].ch[1]);
				return;
			}
			int nxt=x<tree[now].v?0:1;
			if(!tree[now].ch[nxt])
			{
				int p=newpoint(x,now);
				tree[now].ch[nxt]=p;
				splay(p,tree[0].ch[1]);
				return;
			}
			now=tree[now].ch[nxt];
		}
	}
}
inline int find(register int v)
{
	int now=tree[0].ch[1];
	while(19260817)
	{
		if(tree[now].v==v)
		{
			splay(now,tree[0].ch[1]);
			return now;
		}
		int nxt=v<tree[now].v?0:1;
		if(!tree[now].ch[nxt])
			return 0;
		now=tree[now].ch[nxt];
	}
}
inline void delet(register int x)
{
	int pos=find(x);
	if(!pos)
		return;
	if(tree[pos].rec>1)
	{
		--tree[pos].rec;
		--tree[pos].sum;
	}
	else
	{
		if(!tree[pos].ch[0]&&!tree[pos].ch[1])
			tree[0].ch[1]=0;
		else if(!tree[pos].ch[0])
		{
			tree[0].ch[1]=tree[pos].ch[1];
			tree[tree[0].ch[1]].fa=0;
		}
		else
		{
			int left=tree[pos].ch[0];
			while(tree[left].ch[1])
				left=tree[left].ch[1];
			splay(left,tree[pos].ch[0]);
			connect(tree[pos].ch[1],left,1);
			connect(left,0,1);
			update(left);
		}
	}
}
inline int arank(register int x)
{
	int now=tree[0].ch[1];
	while(19260817)
	{
		int used=tree[now].sum-tree[tree[now].ch[1]].sum;
		if(x>tree[tree[now].ch[0]].sum&&x<=used)
		{
			splay(now,tree[0].ch[1]);
			return tree[now].v;
		}
		if(x<used)
			now=tree[now].ch[0];
		else
			x-=used,now=tree[now].ch[1];
	}
}
struct query{
	int l,r,id,bl,k;
}q[M];
int a[N],blocksize=0,ans[M];
inline bool cmp(register query a,register query b)
{
	return a.bl!=b.bl?a.l<b.l:((a.bl&1)?a.r<b.r:a.r>b.r);
}
int main()
{
	int n=read(),m=read();
	blocksize=sqrt(m);
	for(register int i=1;i<=n;++i)
		a[i]=read();
	for(register int i=1;i<=m;++i)
	{
		int l=read(),r=read(),k=read();
		q[i]=(query){l,r,i,l/blocksize,k};
	}
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	for(register int i=1;i<=m;++i)
	{
		int ll=q[i].l,rr=q[i].r;
		while(ll<l)
			Insert(a[--l]);
		while(rr>r)
			Insert(a[++r]);
		while(ll>l)
			delet(a[l++]);
		while(rr<r)
			delet(a[r--]);
		ans[q[i].id]=arank(q[i].k);
	}
	for(register int i=1;i<=m;++i)
		write(ans[i]),puts("");
	return 0;
}
posted @ 2018-11-25 16:04  JSOI爆零珂学家yzhang  阅读(349)  评论(0编辑  收藏  举报