POJ 2104 K-th Number
我的第一道整体二分
要注意的是cnt1,cnt2一定不能开成全局变量
不然你下一次调用它的时候就已经被改了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXNM=105005;
const int MAXN=100005;
const int MAXM=5005;
const int inf=0x3f3f3f3f;
inline int read(){
int x=0,f=1,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int data[MAXN],n;
inline void add(int x,int i){
while(x<=n) data[x]+=i,x+=x&(-x);
}
inline int query(int x){
int res=0;
while(x) res+=data[x],x-=x&(-x);
return res;
}
struct stu{
int op,id,l,r,k;
};
stu q[MAXNM],q1[MAXNM],q2[MAXNM];
int cnt;
int ans[MAXM];
inline void erfen(int l,int r,int sl,int sr){
if(sr<sl) return ;
if(l==r){
// cout<<l<<endl;
// cout<<sl<<"\t"<<sr<<endl;
for(int i=sl;i<=sr;i++)
if(q[i].op==1)
ans[q[i].id]=l;
return ;
}
// cout<<l<<"\t"<<r<<"\t"<<sl<<"\t"<<sr<<endl;
int cnt1=0,cnt2=0;
int mid=(l+r)>>1;
for(int i=sl;i<=sr;i++){
if(q[i].op==0){
if(q[i].k<=mid) add(q[i].l,1),q1[++cnt1]=q[i];
else q2[++cnt2]=q[i];
}
else{
int res=query(q[i].r)-query(q[i].l-1);
if(res>=q[i].k) q1[++cnt1]=q[i];
else q[i].k-=res,q2[++cnt2]=q[i];
}
}
for(int i=sl;i<=sr;i++)
if(q[i].op==0&&q[i].k<=mid)
add(q[i].l,-1);
for(int i=1;i<=cnt1;i++) q[sl+i-1]=q1[i];
for(int i=1;i<=cnt2;i++) q[sl+cnt1+i-1]=q2[i];
erfen(l,mid,sl,sl+cnt1-1);
erfen(mid+1,r,sl+cnt1,sr);
}
int main(){
n=read();int m=read();
for(int i=1;i<=n;i++){
int x=read();
q[++cnt]=(stu){0,0,i,i,x};
}
for(int i=1;i<=m;i++){
int l=read(),r=read(),k=read();
q[++cnt]=(stu){1,i,l,r,k};
}
erfen(-inf,inf,1,cnt);
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号