[Bzoj1901]Zju2112 Dynamic Rankings

/*1.change后要更新a数组
  2.删除节点后子节点数量-1*/
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define N 200010
#define M 1300010
#define inf 1000000000
using namespace std;
struct data{
	int l,r,s,w,v,rnd;
}tr[M];
int root[N],a[50001],n,m,sz,tmp; 
void update(int k){
	tr[k].s=tr[tr[k].l].s+tr[tr[k].r].s+tr[k].w;
}
void lturn(int &k){
	int t=tr[k].r;
	tr[k].r=tr[t].l;
	tr[t].l=k;
	tr[t].s=tr[k].s;
	update(k);k=t;	
}
void rturn(int &k){
	int t=tr[k].l;
	tr[k].l=tr[t].r;
	tr[t].r=k;
	tr[t].s=tr[k].s;
	update(k);k=t;
}
void insert(int &k,int num){
	if(!k){
		k=++sz;
		tr[k].s=tr[k].w=1;
		tr[k].rnd=rand();
		tr[k].l=tr[k].r=0;
		tr[k].v=num;
		return;
	}
	tr[k].s++;
	if(tr[k].v==num)tr[k].w++;
	else if(num<tr[k].v){
		insert(tr[k].l,num);
		if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k);
	}
	else{
		insert(tr[k].r,num);
		if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);
	}
}
void del(int &k,int num){
	if(tr[k].v==num){
		if(tr[k].w>1){tr[k].w--;tr[k].s--;return;}
		else if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;
		else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd){
			rturn(k);del(k,num);
		}
		else{
			lturn(k);del(k,num);
		}
	}
	else if(num<tr[k].v){
		del(tr[k].l,num);tr[k].s--;
	}
	else{
		del(tr[k].r,num);tr[k].s--;
	}
}
void change(int k,int l,int r,int x,int num,int y){
	del(root[k],y);
	insert(root[k],num);
	if(l==r)return;
	int mid=(l+r)>>1;
	if(x<=mid)change(k<<1,l,mid,x,num,y);
	else change(k<<1|1,mid+1,r,x,num,y);
}
void build(int k,int l,int r,int x,int num){
	insert(root[k],num);
	if(l==r)return;
	int mid=(l+r)>>1;
	if(x<=mid)build(k<<1,l,mid,x,num);
	else build(k<<1|1,mid+1,r,x,num);
}
void get_rank(int k,int num){
	if(!k)return;
	if(num>=tr[k].v){
		tmp+=tr[tr[k].l].s+tr[k].w;
		get_rank(tr[k].r,num);
	}
	else get_rank(tr[k].l,num);
}
void ask_rank(int k,int l,int r,int x,int y,int num){
	if(l==x&&r==y){get_rank(root[k],num);return;}
	int mid=(l+r)>>1;
	if(y<=mid)ask_rank(k<<1,l,mid,x,y,num);
	else if(x>mid)ask_rank(k<<1|1,mid+1,r,x,y,num);
	else{
		ask_rank(k<<1,l,mid,x,mid,num);
		ask_rank(k<<1|1,mid+1,r,mid+1,y,num);
	}
}
void ask_index(int x,int y,int z){
    int l=0,r=inf,ans;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        tmp=1;ask_rank(1,1,n,x,y,mid);
        if(tmp<=z){l=mid+1;ans=mid;}
        else r=mid-1;
        }
    printf("%d\n",l);
}
int main(){
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		for(int i=1;i<=n;i++)build(1,1,n,i,a[i]);
		for(int i=1;i<=m;i++){
			char s[3];int x,y,z;
			scanf("%s",s);
			if(s[0]=='Q'){
				scanf("%d%d%d",&x,&y,&z);
				ask_index(x,y,z);
			}
			else if(s[0]=='C'){
				scanf("%d%d",&x,&y);
				change(1,1,n,x,y,a[x]);
				a[x]=y;
			}
		}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值