题目链接
求动态第k小,并且实时更新。
树状数组套权值线段树
讲这题的有篇博客的图很好,附个链接:洛谷P2617 Dynamic Rankings 树状数组+主席树
洛谷上我过了,自己oj上超时,可能自己学校oj有点不行。
rt[i]
不再仅仅表示第 i 个延伸的树,如
第1棵主席树表示第1个点的权值的集合。
第2棵主席树表示第1、2个点的权值的集合。
第3棵主席树表示第3个点的权值的集合。
第4棵主席树表示第1、2、3、4个点的权值的集合。
#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return x*f;
}
char getch(){
char ch=getchar();
while(ch!='Q' && ch!='C') ch=getchar();
return ch;
}
const int maxn=2e5+7;
int n,m,cnt,c,a[maxn],b[maxn<<1],t[maxn];
int rt[maxn*400],L[maxn*400],R[maxn*400],sum[maxn*400];
int op[maxn],x[maxn],y[maxn],z[maxn];
int lc,rc,tl[maxn],tr[maxn];
int lowbit(int x){ return x&(-x); }
void update(int &i,int pre,int l,int r,int x,int v){
i=++cnt; L[i]=L[pre]; R[i]=R[pre];
sum[i]=sum[pre]+v;
if(l==r) return;
int mid=l+r>>1;
if(x<=mid) update(L[i],L[pre],l,mid,x,v);
else update(R[i],R[pre],mid+1,r,x,v);
}
int query(int l,int r,int k){
if(l==r) return l;
int mid=l+r>>1,ans=0;
for(int i=1;i<=lc;i++) ans-=sum[L[tl[i]]];
for(int i=1;i<=rc;i++) ans+=sum[L[tr[i]]];
if(k<=ans){
for(int i=1;i<=lc;i++) tl[i]=L[tl[i]];
for(int i=1;i<=rc;i++) tr[i]=L[tr[i]];
return query(l,mid,k);
}
else{
for(int i=1;i<=lc;i++) tl[i]=R[tl[i]];
for(int i=1;i<=rc;i++) tr[i]=R[tr[i]];
return query(mid+1,r,k-ans);
}
}
void modify(int x,int v){
int k=lower_bound(b,b+c,a[x])-b;
for(int i=x;i<=n;i+=lowbit(i)) update(rt[i],rt[i],0,c-1,k,v);
}
int ask(int l,int r,int k){
lc=rc=0;
for(int i=l-1;i;i-=lowbit(i)) tl[++lc]=rt[i];
for(int i=r;i;i-=lowbit(i)) tr[++rc]=rt[i];
return query(0,c-1,k);
}
int main(){
c=n=read(); m=read();
for(int i=1;i<=n;i++) b[i-1]=a[i]=read();
for(int i=0;i<m;i++){
char ch=getch(); x[i]=read(); y[i]=read();
if(ch=='C'){
op[i]=1;
b[c++]=y[i];
}
else z[i]=read();
}
sort(b,b+c); c=unique(b,b+c)-b;
for(int i=1;i<=n;i++) modify(i,1);
for(int i=0;i<m;i++){
if(op[i]){
modify(x[i],-1);
a[x[i]]=y[i];
modify(x[i],1);
}
else printf("%d\n",b[ask(x[i],y[i],z[i])]);
}
}
/*
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
3
6
*/