线段树套平衡树

没什么好讲的,直接码就完了。

#include<bits/stdc++.h>
#define ll long long
#define db double 
#define filein(a) freopen(#a".in","r",stdin)
#define fileot(a) freopen(#a".out","w",stdout)
#define Better_IO false
namespace IO{
	#if Better_IO
		char buf[(1<<20)+3],*p1(buf),*p2(buf);
		const int lim=1<<20;
		inline char gc(){
			if(p1==p2) p2=(p1=buf)+fread(buf,1,lim,stdin);
			return p1==p2?EOF:*p1++;
		}
		#define pc putchar
	#else
		#define gc getchar
		#define pc putchar
	#endif
	inline bool blank(char c){
		return c=='\t' or c=='\n' or c=='\r' or c==' ' or c==EOF;
	}
	inline void gs(char *s){
		char ch=gc();
		while(blank(ch) ) ch=gc();
		while(!blank(ch) ) {*s++=ch;ch=gc();}
		*s=0;
	}
	inline void ps(char *s){
		while(*s!=0) {pc(*s++);}
	}
	template<class T>
	inline void read(T &s){
		s=0;char ch=gc();bool f=0;
		while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
		while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
		if(ch=='.'){
			db p=0.1;ch=gc();
			while('0'<=ch&&ch<='9') {s=s+p*(ch^48);ch=gc();p*=0.1;}
		}
		s=f?-s:s;
	}
	template<class T,class ...A>
	inline void read(T &s,A &...a){
		read(s);read(a...);
	}
};
using IO::gs;
using IO::ps;
using IO::read;
const int N=5e4+3;
const int inf=1e9;
int n,m;
int a[N];
struct Scapegoat{
	#define lc(x) t[x].lc
	#define rc(x) t[x].rc
	const db alpha=0.7;
	int tot;
	struct node{
		int lc,rc,cnt;
		int k,sz,fc;
	}t[(N<<1)*16*16];
	inline void pushup(int x){
		t[x].sz=t[lc(x)].sz+t[rc(x)].sz+1;
		t[x].fc=t[lc(x)].fc+t[rc(x)].fc+t[x].cnt;
	}
	inline bool canrbu(int x){
		return t[x].cnt and (
			t[x].sz*alpha<=(db)std::max(t[lc(x)].sz,t[rc(x)].sz) or
			(db)t[x].fc<=t[x].sz*alpha
		);
	}
	int top,fd[(N<<1)*16];
	void rbu_ldr(int x){
		if(!x) return;
		rbu_ldr(lc(x) );
		if(t[x].cnt) fd[++top]=x;
		rbu_ldr(rc(x) );
	}
	int rbu_build(int l,int r){
		if(l>r) return 0;
		int mid=(l+r)>>1;
		lc(fd[mid])=rbu_build(l,mid-1);
		rc(fd[mid])=rbu_build(mid+1,r);
		pushup(fd[mid]);
		return fd[mid];
	}
	inline void rbu(int &x){
		top=0;rbu_ldr(x);
		x=rbu_build(1,top);
	}
	void ins(int &x,int k){
		if(!x){
			x=++tot;
			t[x].k=k;
			++t[x].cnt;
			pushup(x);
			return;
		}
		if(t[x].k==k){
			++t[x].cnt;
		}else if(t[x].k<k){
			ins(rc(x),k);
		}else{
			ins(lc(x),k);
		}
		pushup(x);
		if(canrbu(x) ) rbu(x);
	}
	void del(int &x,int k){
		if(!x) return;
		if(t[x].k==k){
			if(t[x].cnt) --t[x].cnt;
		}else if(t[x].k<k){
			del(rc(x),k);
		}else{
			del(lc(x),k);
		}
		pushup(x);
		if(canrbu(x) ) rbu(x);
	}
	int upper(int x,int k){
		if(!x) return 0;
		if(t[x].k==k) return t[lc(x)].fc;
		if(k<t[x].k) return upper(lc(x),k);
		return t[lc(x)].fc+t[x].cnt+upper(rc(x),k);
	}
	int kth(int x,int k){
		if(!x) return 0;
		if(t[lc(x)].fc<k and k<=t[lc(x)].fc+t[x].cnt)
			return t[x].k;
		if(k<=t[lc(x)].fc) return kth(lc(x),k);
		return kth(rc(x),k-t[lc(x)].fc-t[x].cnt);
	}
	inline int pre(int x,int k){
		int s=upper(x,k);
		if(s<=0) return -inf;
		return kth(x,s);
	}
	inline int nxt(int x,int k){
		int s=upper(x,k+1)+1;
		if(s>t[x].fc) return inf;
		return kth(x,s);
	}
	#undef lc
	#undef rc
}s2;
struct SegTree{
	#define lc(x) (x<<1)
	#define rc(x) (x<<1|1)
	struct node{
		int l,r,mid;
		int rt;
	}t[N<<2];
	inline void build(int x,int l,int r){
		t[x].l=l;t[x].r=r;t[x].mid=(l+r)>>1;
		for(int i=l;i<=r;++i){
			s2.ins(t[x].rt,a[i]);
		}
		if(l==r){
			return;
		}
		build(lc(x),l,t[x].mid);
		build(rc(x),t[x].mid+1,r);
	}
	inline int upper(int x,int l,int r,int k){
		if(l<=t[x].l and t[x].r<=r){
			return s2.upper(t[x].rt,k);
		}
		int res=0;
		if(l<=t[x].mid) res+=upper(lc(x),l,r,k);
		if(t[x].mid+1<=r) res+=upper(rc(x),l,r,k);
		return res;
	}
	inline void modify(int x,int p,int a,int b){
		s2.del(t[x].rt,a);
		s2.ins(t[x].rt,b);
		if(p<=t[x].l and t[x].r<=p){
			return;
		}
		if(p<=t[x].mid) modify(lc(x),p,a,b);
		if(t[x].mid+1<=p) modify(rc(x),p,a,b);
	}
	inline int pre(int x,int l,int r,int k){
		if(l<=t[x].l and t[x].r<=r){
			return s2.pre(t[x].rt,k);
		}
		int res=-inf;
		if(l<=t[x].mid) res=std::max(res,pre(lc(x),l,r,k) );
		if(t[x].mid+1<=r) res=std::max(res,pre(rc(x),l,r,k) );
		return res;
	}
	inline int nxt(int x,int l,int r,int k){
		if(l<=t[x].l and t[x].r<=r){
			return s2.nxt(t[x].rt,k);
		}
		int res=inf;
		if(l<=t[x].mid) res=std::min(res,nxt(lc(x),l,r,k) );
		if(t[x].mid+1<=r) res=std::min(res,nxt(rc(x),l,r,k) );
		return res;
	}
	#undef lc
	#undef rc
}s1;
int main(){
	//filein(a);fileot(a);
	read(n,m);
	for(int i=1;i<=n;++i){
		read(a[i]);
	}
	s1.build(1,1,n);
	for(int i=1;i<=m;++i){
		int op;read(op);
		int l,r,p,k;
		int t=clock();
		if(op==1){
			read(l,r,k);
			printf("%d\n",s1.upper(1,l,r,k)+1);
		}
		if(op==2){
			read(l,r,k);
			int el=0,er=1e8,eres=0;
			int tim=0;
			while(el<=er){
				++tim;
				int emid=(el+er)>>1;
				if(s1.upper(1,l,r,emid)<k){
					el=emid+1;eres=emid;
				}else er=emid-1;
			}
			printf("%d\n",eres);
		}
		if(op==3){
			read(p,k);
			s1.modify(1,p,a[p],k);
			a[p]=k;
		}
		if(op==4){
			read(l,r,k);
			int s=s1.pre(1,l,r,k);
			if(s!=-inf)
				printf("%d\n",s);
			else printf("-2147483647\n");
		}
		if(op==5){
			read(l,r,k);
			int s=s1.nxt(1,l,r,k);
			if(s!=inf)
				printf("%d\n",s);
			else printf("2147483647\n");
		}
	}
	fprintf(stderr,"%dms\n",clock() );
	return 0;
}
posted @ 2022-04-15 16:22  cbdsopa  阅读(23)  评论(0编辑  收藏  举报