1. 程式人生 > 實用技巧 >Dynamic Rankings(資料結構)

Dynamic Rankings(資料結構)

description

給定一個長度為\(n\)的序列\(\{ a \}\),需支援兩種操作:查詢區間\([L,R]\)中第\(k\)小的數;將\(a_{x}\)改為\(y\).

solution

此題需支援動態區間kth查詢,不難想到用主席樹進行維護,然後至於單點修改操作,可以用樹狀陣列維護字首和.

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#define R register
#define next kdjadskfj
#define debug puts("mlg")
#define mod 10000000007
#define Mod(x) ((x%mod+mod)%mod)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writeln(ll x);
inline void writesp(ll x);
inline ll lowbit(ll x){return x&-x;}
const ll maxn=1e6+5;
struct node{
	ll op,l,r,k,x,y;
}q[maxn];
ll n,m;
ll a[maxn];
ll lsh[maxn<<1],h;
ll rt[maxn<<1],cnt;
struct seg{
	ll ls,rs,dat;
}t[maxn<<4];
ll temp[2][maxn],tot[2];

inline void update(ll &p,ll l,ll r,ll k,ll val){
	if(!p) p=++cnt;
	t[p].dat+=val;
	if(l==r) return;
	ll mid=l+r>>1;
	if(k<=mid) update(t[p].ls,l,mid,k,val);
	else update(t[p].rs,mid+1,r,k,val);
}

inline void True_update(ll pos,ll val){
	for(R ll i=pos;i<=n;i+=lowbit(i)) update(rt[i],1,h,a[pos],val);
}

inline ll query(ll l,ll r,ll k){
	if(l==r) return l;
	ll mid=l+r>>1,sum=0;
	for(R ll i=1;i<=tot[0];i++) sum+=t[t[temp[0][i]].ls].dat;
	for(R ll i=1;i<=tot[1];i++) sum-=t[t[temp[1][i]].ls].dat;
	if(k<=sum){
		for(R ll i=1;i<=tot[0];i++) temp[0][i]=t[temp[0][i]].ls;
		for(R ll i=1;i<=tot[1];i++) temp[1][i]=t[temp[1][i]].ls;
		return query(l,mid,k);
	}
	else{
		for(R ll i=1;i<=tot[0];i++) temp[0][i]=t[temp[0][i]].rs;
		for(R ll i=1;i<=tot[1];i++) temp[1][i]=t[temp[1][i]].rs;
		return query(mid+1,r,k-sum);
	}
}

inline ll True_query(ll l,ll r,ll k){
	tot[0]=tot[1]=0;
	for(R ll i=r;i;i-=lowbit(i)) temp[0][++tot[0]]=rt[i];
	for(R ll i=l-1;i;i-=lowbit(i)) temp[1][++tot[1]]=rt[i];
	return query(1,h,k);
}
int main(){
	n=read();m=read();
	for(R ll i=1;i<=n;i++) a[i]=lsh[++h]=read();	
	for(R ll i=1;i<=m;i++){
		char wn=getchar();
		while(wn!='Q'&&wn!='C') wn=getchar();
		if(wn=='Q'){
			q[i].op=1;q[i].l=read();q[i].r=read();q[i].k=read();
		}
		else{
			q[i].op=2;q[i].x=read();lsh[++h]=q[i].y=read();
		}
	}
	sort(lsh+1,lsh+h+1);
	h=unique(lsh+1,lsh+h+1)-lsh-1;
	for(R ll i=1;i<=n;i++) a[i]=lower_bound(lsh+1,lsh+h+1,a[i])-lsh;
	for(R ll i=1;i<=n;i++) True_update(i,1);
	for(R ll i=1;i<=m;i++){
		if(q[i].op==1){
			writeln(lsh[True_query(q[i].l,q[i].r,q[i].k)]);
		}
		else{
			True_update(q[i].x,-1);
			a[q[i].x]=lower_bound(lsh+1,lsh+h+1,q[i].y)-lsh;
			True_update(q[i].x,1);
		}
	}
}
inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x);putchar(' ');}
inline void writeln(ll x){write(x);putchar('\n');}