比赛 清华集训2017模板练习 评测结果 AAAAAAAAAA
题目名称 二逼平衡树 最终得分 100
用户昵称 FoolMike 运行时间 1.656 s
代码语言 C++ 内存使用 229.96 MiB
提交时间 2017-12-02 21:28:07
显示代码纯文本
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10,M=2e7+10;
struct node{int l,r,v;}nd[M];
int n,m,id,a[N];
int add(int x,int l,int r,int p,int d){
	int now=++id;
	nd[now]=nd[x];
	nd[now].v+=d;
	if (l==r) return now;
	int mid=(l+r)>>1;
	if (p>mid) nd[now].r=add(nd[x].r,mid+1,r,p,d);
		else nd[now].l=add(nd[x].l,l,mid,p,d);
	return now;
}
int query(int x,int l,int r,int L,int R){
	if (l>=L&&r<=R) return nd[x].v;
	int mid=(l+r)>>1,ans=0;
	if (L<=mid) ans+=query(nd[x].l,l,mid,L,R);
	if (R>mid) ans+=query(nd[x].r,mid+1,r,L,R);
	return ans;
}
int root[N];
void add(int p,int v,int d){
	for (;p<=n;p+=p&-p) root[p]=add(root[p],0,1e8,v,d);
}
int rk(int p,int v){
	if (v<=0) return 0;
	v=min(v,(int)1e8+1);
	int ans=0;
	for (;p;p-=p&-p) ans+=query(root[p],0,1e8,0,v-1);
	return ans;
}
int rk(int l,int r,int v){
	return rk(r,v)-rk(l-1,v)+1;
}
int ql[N],cl,qr[N],cr;
int find(int l,int r,int v){
	for (cr=0;r;r-=r&-r) qr[++cr]=root[r];
	for (cl=0,l--;l;l-=l&-l) ql[++cl]=root[l];
	int L=0,R=1e8;
	while (L<R){
		int mid=(L+R)>>1,s=0;
		for (int i=1;i<=cl;i++) s-=nd[nd[ql[i]].l].v;
		for (int i=1;i<=cr;i++) s+=nd[nd[qr[i]].l].v;
		if (v<=s){
			for (int i=1;i<=cl;i++) ql[i]=nd[ql[i]].l;
			for (int i=1;i<=cr;i++) qr[i]=nd[qr[i]].l;
			R=mid;
		}
		else{
			for (int i=1;i<=cl;i++) ql[i]=nd[ql[i]].r;
			for (int i=1;i<=cr;i++) qr[i]=nd[qr[i]].r;
			L=mid+1;v-=s;
		}
	}
	return L;
}
int pre(int l,int r,int k){
	return find(l,r,rk(l,r,k)-1);
}
int suf(int l,int r,int k){
	return find(l,r,rk(l,r,k+1));
}
int main()
{
	freopen("psh.in","r",stdin);
	freopen("psh.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]),add(i,a[i],1);
	for (int i=1;i<=m;i++){
		int tp,l,r,v;
		scanf("%d%d%d",&tp,&l,&r);
		if (tp==3) add(l,a[l],-1),add(l,a[l]=r,1);
			else scanf("%d",&v);
		if (tp==1) printf("%d\n",rk(l,r,v));
		if (tp==2) printf("%d\n",find(l,r,v));
		if (tp==4) printf("%d\n",pre(l,r,v));
		if (tp==5) printf("%d\n",suf(l,r,v));
	}
	return 0;
}