线段树套权值线段树10~30pts求助
查看原帖
线段树套权值线段树10~30pts求助
209923
PRIMITIVE_LIGHTS楼主2022/2/13 14:53

线段树套权值线段树 一开始Here

开大数组,变成Here

加O2+开大,变成Here 求调 Code:

#include<iostream>
#define L -1
#define R 1e8+1
#define endl '\n'
using namespace std;
int a[50001];
int n,m;
struct node{
	int lc;
	int rc;
	int w;
}tr[30000001];
int cnt=0;
int build(){tr[++cnt].lc=0,tr[cnt].rc=0,tr[cnt].w=0;return cnt;}
struct segment_tree{
	int root=0;
	void pushup(int k){
		tr[k].w=0;
		if(tr[k].lc) tr[k].w=tr[tr[k].lc].w;
		if(tr[k].rc) tr[k].w+=tr[tr[k].rc].w;
	}
	void add(int k,int l,int r,int x,int p){
		if(l==r){tr[k].w+=p;return ;}
		int mid=(l+r)>>1;
		if(x<=mid){if(!tr[k].lc) tr[k].lc=build(); add(tr[k].lc,l,mid,x,p);}
		else{if(!tr[k].rc) tr[k].rc=build();add(tr[k].rc,mid+1,r,x,p);}
		pushup(k);
	}
	int ask(int k,int l,int r,int ql,int qr){
		if(l>=ql&&r<=qr){return tr[k].w;}
		int ret=0;int mid=(l+r)>>1;
		if(ql<=mid) {if(tr[k].lc)ret+=ask(tr[k].lc,l,mid,ql,qr);};
		if(qr>mid) {if(tr[k].rc)ret+=ask(tr[k].rc,mid+1,r,ql,qr);}; 
		return ret;
	}
	int rank(int k){return ask(root,L,R,L,k-1)+1;}
	int kth(int k,int l,int r,int x){
		if(l==r){return l;}int mid=(l+r)>>1;
		if(x<=tr[tr[k].lc].w) return kth(tr[k].lc,l,mid,x);return kth(tr[k].rc,mid+1,r,x-tr[tr[k].lc].w);
	}
	int pre(int k){return kth(root,L,R,rank(k)-1);}
	int nxt(int k){return kth(root,L,R,rank(k)+ask(root,L,R,k,k));}
	
};
struct Node{
	int lc,rc;
	segment_tree w;
}root,TR[200001];
void BUILD(int k,int l,int r){
	TR[k].w.root=build();
	for(int i=l;i<=r;i++) TR[k].w.add(TR[k].w.root,L,R,a[i],1);
	if(l==r) return;
	int mid=(l+r)>>1;
	BUILD(k<<1,l,mid);
	BUILD(k<<1|1,mid+1,r);
}
void change(int k,int l,int r,int pos,int y){
	TR[k].w.add(TR[k].w.root,L,R,a[pos],-1);
	TR[k].w.add(TR[k].w.root,L,R,y,1);
	if(l==r) return;
	int mid=(l+r)>>1;
	if(pos<=mid) change(k<<1,l,mid,pos,y);
	else change(k<<1|1,mid+1,r,pos,y);
}
int Rnk(int k,int l,int r,int x,int ql,int qr){
	if(l>=ql&&r<=qr) return TR[k].w.rank(x)-1;
	int mid=(l+r)>>1,ret=0;
	if(ql<=mid) ret+=Rnk(k<<1,l,mid,x,ql,qr);
	if(qr>mid) ret+=Rnk(k<<1|1,mid+1,r,x,ql,qr);
	return ret;
}
int rnk(int k,int l,int r,int x,int ql,int qr){
	return Rnk(k,l,r,x,ql,qr)+1;
}
int kth(int x,int ql,int qr){
	int ll=L,rr=R;
	int ans=0;
	while(ll<=rr){
		int mid=(ll+rr)>>1;
		if(rnk(1,1,n,mid,ql,qr)<=x)
			ll=mid+1,ans=mid;
		else rr=mid-1;
	}
	return ans;
}
int pre(int l,int r,int k){if(rnk(1,1,n,k,l,r)==1) return -2147483647;return kth(rnk(1,1,n,k,l,r)-1,l,r);}
int nxt(int l,int r,int k){if(rnk(1,1,n,k,l,r)==r-l+1) return 2147483647;return kth(rnk(1,1,n,k+1,l,r),l,r);}
int main(){
//	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	BUILD(1,1,n);
	for(int i=1;i<=m;i++){
		int opt,l,r,k,pos;
//		cin>>l>>r>>k;
		cin>>opt;
		if(opt==1){
			cin>>l>>r>>k;
			cout<<rnk(1,1,n,k,l,r)<<endl;
		}
		if(opt==2){
			cin>>l>>r>>k;
			cout<<kth(k,l,r)<<endl;
		}
		if(opt==3){
			cin>>pos>>k;
			change(1,1,n,pos,k);
		}
		if(opt==4){
			cin>>l>>r>>k;
			cout<<pre(l,r,k)<<endl;
		}
		if(opt==5){
			cin>>l>>r>>k;
			cout<<nxt(l,r,k)<<endl;
		}
	}
}
2022/2/13 14:53
加载中...