luogu P2617 Dynamic Rankings
前置知识:
普通主席树,树状数组
大概
待修主席树
和静态的一样
只不过还要加一颗树
来维护你修改的值
这棵树就是是树状数组,每个节点上再维护一颗动态开点线段树
(就是所说的树套树,不过没啥可怕的,就是麻烦一丢丢)
查询的时候老样子
不过要多加上树状数组中的值罢了
代码还算好些,如果 主席树,树状数组熟的话
末尾
我知道我说的一定看不懂,因为我一开始找了10几篇博客也没看懂
直到看到他们的博客,真的挺详细的,自己看去吧
博客1
博客2
代码
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=2e5+7;
inline int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,w[maxn],rt[maxn],lsh[maxn];
int js,cnt;
int ch[maxn*50][2],siz[maxn*50];
int a[maxn],b[maxn],mmp;
struct QQQ {
char s;
int a,b,c;
}Q[maxn];
inline int lowbit(int x) {return x&-x;}
void build(int &now,int old,int l,int r,int k) {
//@普通主席树建树,一毛一样好吧
//now在old的基础上把k位置上的个数+gs
now=++cnt;
ch[now][0]=ch[old][0];
ch[now][1]=ch[old][1];
siz[now]=siz[old]+1;
if(l==r) return;
int mid=(l+r)>>1;
if(k<=mid) build(ch[now][0],ch[old][0],l,mid,k);
else build(ch[now][1],ch[old][1],mid+1,r,k);
}
void modify(int &now,int l,int r,int k,int gs) {
if(!now) now=++cnt;
siz[now]+=gs;
if(l==r) return;
int mid=(l+r)>>1;
if(k<=mid) modify(ch[now][0],l,mid,k,gs);
else modify(ch[now][1],mid+1,r,k,gs);
}
int query(int now,int old,int l,int r,int k) {
if(l==r) return l;
int tot=siz[ch[now][0]]-siz[ch[old][0]],mid=(l+r)>>1;
for(int i=1;i<=a[0];++i) tot+=siz[ch[a[i]][0]];//,cout<<i<<" "<<a[i]<<"a\n";
for(int i=1;i<=b[0];++i) tot-=siz[ch[b[i]][0]];//,cout<<i<<" "<<b[i]<<"b\n";
if(tot>=k) {
for(int i=1;i<=a[0];++i) a[i]=ch[a[i]][0];
for(int i=1;i<=b[0];++i) b[i]=ch[b[i]][0];
return query(ch[now][0],ch[old][0],l,mid,k);
} else {
for(int i=1;i<=a[0];++i) a[i]=ch[a[i]][1];
for(int i=1;i<=b[0];++i) b[i]=ch[b[i]][1];
return query(ch[now][1],ch[old][1],mid+1,r,k-tot);
}
}
int main() {
//read
n=read(),m=read();
FOR(i,1,n) lsh[i]=w[i]=read();
js=n;
char s[100];
FOR(i,1,m) {
scanf("%s",s);
if(s[0]=='Q') {
Q[i].s='Q';
Q[i].a=read();
Q[i].b=read();
Q[i].c=read();
} else {
Q[i].s='C';
Q[i].a=read();
Q[i].b=read();
lsh[++js]=Q[i].b;
}
}
//lsh
sort(lsh+1,lsh+1+js);
js=unique(lsh+1,lsh+1+js)-lsh-1;
FOR(i,1,n)
w[i]=lower_bound(lsh+1,lsh+1+js,w[i])-lsh;
FOR(i,1,m)
if(Q[i].s=='C')
Q[i].b=lower_bound(lsh+1,lsh+1+js,Q[i].b)-lsh;
//init
FOR(i,1,n) build(rt[i],rt[i-1],1,js,w[i]);
FOR(i,1,m) {
if(Q[i].s=='Q') {
a[0]=b[0]=0;
for(int j=Q[i].b;j>=1;j-=lowbit(j)) a[++a[0]]=rt[j+n];//now
for(int j=Q[i].a-1;j>=1;j-=lowbit(j)) b[++b[0]]=rt[j+n];//old
int ans=query(rt[Q[i].b],rt[Q[i].a-1],1,js,Q[i].c);
cout<<lsh[ans]<<"\n";
} else {
for(int j=Q[i].a;j<=n;j+=lowbit(j)) {
modify(rt[j+n],1,js,w[Q[i].a],-1);
modify(rt[j+n],1,js,Q[i].b,1);
}
w[Q[i].a]=Q[i].b;
}
}
return 0;
}