社区讨论

一个奇怪的想法,本来应该T,但是RE了?

P3834【模板】可持久化线段树 2参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@lo1ul4fc
此快照首次捕获于
2023/10/23 03:14
2 年前
此快照最后确认于
2023/11/03 03:45
2 年前
查看原帖
一颗 Fhq Treap ,莫队思想,只是乱搞,勿喷
CPP
#include<bits/stdc++.h>     // 莫队 + FHQ Treap 实现静态区间第k小问题 
#define Ls(x) tree[(x)].ls
#define Rs(x) tree[(x)].rs
#define ll long long
using namespace std;
const int N=5e5+7;
struct query
{
	int l,r,k,id;
}q[N];
int n,m,a[N],block; 
ll ans[N],res;
class Fhq_Treap      //友善的Fhq Treap
{
	private:
		struct Node
		{
			int pri,ls,rs,siz,key;
		}tree[N];
		int Total,Root;
		void pushup(int x)
		{
			if(!x)
				return;
			tree[x].siz=tree[Ls(x)].siz+tree[Rs(x)].siz+1;
			return;
		}
		int create(int x)
		{
			int rt=++Total;
			tree[rt]={rand(),0,0,1,x};
			return rt;
		}
		void Split(int x,int key,int &L,int &R)
		{
			if(!x)
			{
				L=R=0;
				return;
			}
			if(tree[x].key<=key)
			{
				L=x;
				Split(Rs(x),key,Rs(x),R);
			} 
			else
			{
				R=x;
				Split(Ls(x),key,L,Ls(x));
			}
			pushup(x);
			return;
		}
		int Merge(int x,int y)
		{
			if(!x||!y)
				return x+y;
			if(tree[x].pri>tree[y].pri)
			{
				Rs(x)=Merge(Rs(x),y);
				pushup(x);
				return x;
			}
			else
			{
				Ls(y)=Merge(x,Ls(y));
				pushup(y);
				return y;
			}
		}
	public:
		void Insert(int key)
		{
			int x,y;
			Split(Root,key-1,x,y);
			Root=Merge(Merge(x,create(key)),y);
			return;
		}
		void Remove(int key)
		{
			int x,y,z;
			Split(Root,key,x,z);
			Split(x,key-1,x,y);
			if(y)
				y=Merge(Ls(y),Rs(y));
			Root=Merge(Merge(x,y),z);
			return;
		}
		int Kth(int k)
		{
			int x=Root;
			for(;;)
			{
				if(tree[Ls(x)].siz+1==k)
					break;
				else if(tree[Ls(x)].siz+1>k)
					x=Ls(x);
				else
				{
					k-=tree[Ls(x)].siz+1;
					x=Rs(x);
				}
			}
			return tree[x].key;
		}
};
Fhq_Treap treap;
inline bool cmp(query x,query y)
{
	if((x.l-1)/block==(y.l-1)/block)
		return x.r<y.r;
	return x.l/block<y.l/block;
}
inline void ins(int x)
{
	treap.Insert(x);
	return;
}
inline void del(int x)
{
	treap.Remove(x);
	return;
}
int main()
{
	srand(time(0));
	scanf("%d%d",&n,&m);
	block=sqrt(n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(int i=1,l,r,k;i<=m;i++)
	{
		scanf("%d%d%d",&l,&r,&k);
		q[i]={l,r,k,i};
	}
	sort(q+1,q+1+m,cmp);      //莫队排序
//	for(int i=1;i<=n;i++)
//	{
//		treap.Insert(a[i]);
//	}
//	for(int i=1;i<=n;i++)
//	{
//		printf("%d\n",a[treap.kth(treap.root,i)]);
//	}
	int L=q[1].l,R=q[1].r;
	for(int i=L;i<=R;i++)
	{
		ins(a[i]);
	}
//	printf("First L is : %d\n First R is : %d\n",L,R);
//	for(int i=1;i<=m;i++)
//	{
//		printf("%d %d %d %d\n",q[i].l,q[i].r,q[i].k,q[i].id);
//	}
	ans[q[1].id]=treap.Kth(q[1].k); //先查了第一询问作为初始端点
	for(int i=2;i<=m;i++)
	{
		int l=q[i].l,r=q[i].r;
//		printf("%d %d %d %d\n",l,r,q[i].k,q[i].id);
		while(L>l) 
		{ 
			ins(a[--L]);
		} 
		while(R<r)
		{
			ins(a[++R]);
		}
		while(L<l)
		{
			del(a[L++]);
		}
		while(R>r)
		{
			del(a[R--]);
		}
		ans[q[i].id]=treap.Kth(q[i].k);
	}
	for(int i=1;i<=m;i++)
	{
		printf("%lld\n",ans[i]);
	}
    return 0;
}

悬关

回复

3 条回复,欢迎继续交流。

正在加载回复...