整体二分

NKOJ2670 动态区间第K小数

%%%a58124751…

整体二分

二分一个mid,以时间顺序讨论,对于值小于等于mid的数和修改,用树状数组统计起来

由于是以时间顺序讨论,所以当前讨论的询问中,若满足k个,说明它的答案是小于mid的(因为树状数组里只统计了小于mid的值),将它划到左边继续讨论

对于不满足k个的,去掉小于mid的影响,放入右边讨论

对于数和修改,也按照mid进行划分

直到分治到底层,这时询问都已有了答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=200005;

struct Data{
int x,y,k,opt,id;
}Q[N],q1[N],q2[N];
int n,m,tot,qr,a[N],Ans[N],tmp[N];
int c[N];
void modify(int x,int d){
for(int i=x;i<=n;i+=i&-i)c[i]+=d;
}
int getsum(int x){
int sum=0;
for(int i=x;i>=1;i^=i&-i)sum+=c[i];
return sum;
}
void DC(int hd,int tl,int l,int r){
if(hd>tl)return;
if(l==r){
for(int i=hd;i<=tl;i++)
if(Q[i].opt==3)Ans[Q[i].id]=l;
return;
}
int i,j,k,tl1=0,tl2=0,mid=l+r>>1;
for(i=hd;i<=tl;i++){
if(Q[i].opt==1&&Q[i].y<=mid)modify(Q[i].x,1);
else if(Q[i].opt==2&&Q[i].y<=mid)modify(Q[i].x,-1);
else if(Q[i].opt==3)tmp[i]=getsum(Q[i].y)-getsum(Q[i].x-1);
}
for(i=hd;i<=tl;i++){
if(Q[i].opt==1&&Q[i].y<=mid)modify(Q[i].x,-1);
else if(Q[i].opt==2&&Q[i].y<=mid)modify(Q[i].x,1);
}
for(i=hd;i<=tl;i++){
if(Q[i].opt==3){
if(tmp[i]>=Q[i].k)q1[++tl1]=Q[i];
else Q[i].k-=tmp[i],q2[++tl2]=Q[i];
}
else{
if(Q[i].y<=mid)q1[++tl1]=Q[i];
else q2[++tl2]=Q[i];
}
}
for(i=1;i<=tl1;i++)Q[hd+i-1]=q1[i];
for(i=1;i<=tl2;i++)Q[hd+tl1+i-1]=q2[i];
DC(hd,hd+tl1-1,l,mid);
DC(hd+tl1,tl,mid+1,r);
}
int main(){
int i,j,k,x,y,z,maxx=0;
char opt;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
maxx=max(maxx,a[i]);
Q[++tot].x=i,Q[tot].y=a[i];
Q[tot].opt=1;
}
for(i=1;i<=m;i++){
opt=getchar();
while(opt<'A'||opt>'Z')opt=getchar();
if(opt=='Q'){
scanf("%d%d%d",&x,&y,&z);
Q[++tot].x=x,Q[tot].y=y,Q[tot].k=z;
Q[tot].id=++qr;
Q[tot].opt=3;
}
else{
scanf("%d%d",&x,&y);
maxx=max(maxx,y);
Q[++tot].x=x,Q[tot].y=a[x];
Q[tot].opt=2;
Q[++tot].x=x,Q[tot].y=y;
Q[tot].opt=1;
a[x]=y;
}
}
DC(1,tot,1,maxx);
for(i=1;i<=qr;i++)printf("%d\n",Ans[i]);
}