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;
}

  

posted @ 2018-10-08 16:27  古城独钓  阅读(104)  评论(0)    收藏  举报