P2617 Dynamic Rankings
题解:树套树,动态开点线段树套树状数组,这题离线写,要离散化,直接看代码,没什么好说的。
#include<bits/stdc++.h>
#define m (l+r)/2
#define low(x) x&-x
using namespace std;
const int maxn = 1e5+10;
struct node {char op;int l,r,k,pos,v;}qq[maxn];
int n,q,sz,a[maxn],s[maxn*2],V1[30],rt[maxn],cnz,cnt,V2[30][2],cnz1,cnz2;
int sum[maxn*400],ls[maxn*400],rs[maxn*400];
void up(int l,int r,int k,int v){
for(int i=1;i<=cnz;i++)
sum[V1[i]] += v;
if(l==r) return ;
if(k>m){
for(int i=1;i<=cnz;i++)
{
if(!rs[V1[i]]) rs[V1[i]] = ++cnt;
V1[i] = rs[V1[i]];
}
up(m+1,r,k,v);
}
else {
for(int i=1;i<=cnz;i++)
{
if(!ls[V1[i]]) ls[V1[i]] = ++cnt;
V1[i] = ls[V1[i]];
}
up(l,m,k,v);
}
}
void modify(int x,int p,int v)
{
cnz = 0;
int k = lower_bound(s+1,s+1+sz,p) - s ;
for(;x<=n;x+=low(x))
V1[++cnz] = rt[x];
up(1,sz,k,v);
}
int qu(int l,int r,int k)
{
if(l==r) return s[l];
int ans = 0;
for(int i=1;i<=cnz1;i++)
ans += sum[ls[V2[i][0]]];
for(int i=1;i<=cnz2;i++)
ans -= sum[ls[V2[i][1]]];
if(k>ans){
for(int i=1;i<=cnz1;i++)
V2[i][0] = rs[V2[i][0]];
for(int i=1;i<=cnz2;i++)
V2[i][1] = rs[V2[i][1]];
qu(m+1,r,k-ans);
}
else {
for(int i=1;i<=cnz1;i++)
V2[i][0] = ls[V2[i][0]];
for(int i=1;i<=cnz2;i++)
V2[i][1] = ls[V2[i][1]];
qu(l,m,k);
}
}
int query(int x1,int x2,int k){
cnz1 = 0 , cnz2 = 0;
for(x1;x1>0;x1-=low(x1))
V2[++cnz1][0] = rt[x1];
for(x2;x2>0;x2-=low(x2))
V2[++cnz2][1] = rt[x2];
return qu(1,sz,k);
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=1;i<=n;i++)
rt[i] = ++cnt;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[++sz] = a[i];
}
for(int i=1;i<=q;i++)
{
cin>>qq[i].op;
if(qq[i].op=='C'){
cin>>qq[i].pos>>qq[i].v;
s[++sz] = qq[i].v;
}
else {
cin>>qq[i].l>>qq[i].r>>qq[i].k;
}
}
sort(s+1,s+1+sz);
sz = unique(s+1,s+1+sz) - s - 1 ;
for(int i=1;i<=n;i++) modify(i,a[i],1);
for(int i=1;i<=q;i++)
{
if(qq[i].op=='C'){
modify(qq[i].pos,a[qq[i].pos],-1);
a[qq[i].pos] = qq[i].v;
modify(qq[i].pos,qq[i].v,1);
}
else {
printf("%d\n",query(qq[i].r,qq[i].l-1,qq[i].k));
}
}
}