社区讨论

萌新刚学OI两年半,求助一道树套树,悬赏三关

P3380【模板】树套树参与者 1已保存回复 1

讨论操作

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

当前回复
1 条
当前快照
1 份
快照标识符
@lo2afvz4
此快照首次捕获于
2023/10/23 10:38
2 年前
此快照最后确认于
2023/11/03 10:49
2 年前
查看原帖
rt,前三个操作没问题,貌似是前驱后继写挂了
CPP
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10,inf=2147483647;
namespace FHQ{
	struct node{
		int x,rnd,size;
		int ls,rs;
	}tr[N];
	int tot=0;
	class fhq{
	public:
		int root;
		fhq(){
			root=0;
		}
		int newNode(int x){
			tr[++tot]={x,rand(),1,0,0};
			return tot;
		}
		inline void pushup(int x){
			tr[x].size=tr[tr[x].ls].size+tr[tr[x].rs].size+1;
		}
		void split(int u,int &x,int &y,int val){
			if(!u){
				x=y=0;
				return;
			}
			if(tr[u].x<=val) x=u,split(tr[x].rs,tr[x].rs,y,val);
			else y=u,split(tr[y].ls,x,tr[y].ls,val);
			pushup(u);
		}
		int merge(int x,int y){
			if(!x||!y) return x+y;
			if(tr[x].rnd<tr[y].rnd){
				tr[x].rs=merge(tr[x].rs,y);
				pushup(x);
				return x;
			}
			else{
				tr[y].ls=merge(x,tr[y].ls);
				pushup(y);
				return y;
			}
		}
		void insert(int x){
			int l,r;
			split(root,l,r,x);
			root=merge(l,merge(newNode(x),r));
		}
		void del(int x){
			int l,r,xx,yy;
			split(root,l,r,x);
			split(l,xx,yy,x-1);
			yy=merge(tr[yy].ls,tr[yy].rs);
			root=merge(merge(xx,yy),r);
		}
		int rnk(int x){
			int l,r;
			split(root,l,r,x-1);
			int tmp=tr[l].size+1;
			root=merge(l,r);
			return tmp;
		}
		int kth(int u,int k){
			int p=tr[tr[u].ls].size+1;
			if(k==p) return tr[u].x;
			if(k<p) return kth(tr[u].ls,k);
			return kth(tr[u].rs,k-p);
		}
		int getKth(int x){
			return kth(root,x);
		}
		int pre(int x){
			int l,r;
			split(root,l,r,x-1);
			int tmp=kth(l,tr[l].size);
			root=merge(l,r);
			return tmp;
		}
		int nxt(int x){
			int l,r;
			split(root,l,r,x);
			int tmp=kth(r,1);
			root=merge(l,r);
			return tmp;
		}
	};
}
struct node{
	FHQ::fhq tree;
	int l,r;
}tr[N];
int a[N];
int n,m;
void build(int x,int l,int r){
	tr[x].l=l,tr[x].r=r;
	for(int i=l;i<=r;i++) tr[x].tree.insert(a[i]);
	if(l==r) return;
	int mid=(l+r)/2;
	build(x*2,l,mid),build(x*2+1,mid+1,r);
}
int rnk(int x,int l,int r,int k){
	if(tr[x].l>=l&&tr[x].r<=r) return tr[x].tree.rnk(k)-1;
	int mid=(tr[x].l+tr[x].r)/2,res=0;
	if(l<=mid) res=rnk(x*2,l,r,k);
	if(r>mid) res+=rnk(x*2+1,l,r,k);
	return res;
}
int kth(int l,int r,int k){
	int x=0,y=1e8+10;
	while(x<y){
		int mid=(x+y+1)/2,tmp=rnk(1,l,r,mid);
		if(tmp>=k) y=mid-1;
		else x=mid;
	}
	return x;
}
int pre(int x,int l,int r,int k){
	if(tr[x].l>=l&&tr[x].r<=r) return tr[x].tree.pre(k);
	int mid=(tr[x].l+tr[x].r)/2,maxx=-inf;
	if(l<=mid) maxx=max(maxx,pre(x*2,l,r,k));
	if(r>mid) maxx=max(maxx,pre(x*2+1,l,r,k));
	return maxx;
}
int nxt(int x,int l,int r,int k){
	if(tr[x].l>=l&&tr[x].r<=r) return tr[x].tree.nxt(k);
	int mid=(tr[x].l+tr[x].r)/2,minn=inf;
	if(l<=mid) minn=min(minn,nxt(x*2,l,r,k));
	if(r>mid) minn=min(minn,nxt(x*2+1,l,r,k));
	return minn;
}
int change(int x,int k,int p){
	if(tr[x].l==tr[x].r){
		int tmp=tr[x].tree.getKth(1);
		tr[x].tree.del(tmp);
		tr[x].tree.insert(p);
		return tmp;
	}
	int mid=(tr[x].l+tr[x].r)/2,tmp=0;
	if(k<=mid) tmp=change(x*2,k,p);
	else tmp=change(x*2+1,k,p);
	tr[x].tree.del(tmp);
	tr[x].tree.insert(p);
	return tmp;
}
int main(){
	srand(19260817); 
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(m--){
		int opt,l,r,k;
		cin>>opt>>l>>r;
		if(opt!=3) cin>>k;
		if(opt==1) cout<<rnk(1,l,r,k)+1<<endl;
		if(opt==2) cout<<kth(l,r,k)<<endl;
		if(opt==3) change(1,l,r);
		if(opt==4) cout<<pre(1,l,r,k)<<endl;
		if(opt==5) cout<<nxt(1,l,r,k)<<endl;
	}
}

回复

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

正在加载回复...