[POJ2104]K-th Number(整体二分)

可以整体二分求,当然主席树也可以

Code

 

#include <cstdio>
#include <algorithm>
#define lowbit(x) ((x)&(-x))
#define N 100010
using namespace std;

const int Inf=1e9;
struct node{
	int x,id;
	friend bool operator <(node a,node b){
		return a.x<b.x;
	}
}A[N];
struct que{
	int id,x,y,k,cnt;
}q[N],tmp[N];
int n,m,Ans[N],sum[N];

inline int read(){
    int x=0,f=1;char 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;
}

inline void calc(int l,int r,int ll,int mid){
	int L=1,R=n,M;
	for(;L<R;){
		M=(L+R)>>1;
		if(A[M].x>=ll) R=M;
		else L=M+1;
	}
	for(int i=R;i<=n&&A[i].x<=mid;++i)
		for(int j=A[i].id;j<=n;j+=lowbit(j))
			++sum[j];
	for(int i=l;i<=r;++i){
		q[i].cnt=0;
		for(int j=q[i].y;j;j-=lowbit(j)) q[i].cnt+=sum[j];
		for(int j=q[i].x-1;j;j-=lowbit(j)) q[i].cnt-=sum[j];
	}
	for(int i=R;i<=n&&A[i].x<=mid;++i)
		for(int j=A[i].id;j<=n;j+=lowbit(j))
			--sum[j];
}

inline void slove(int l,int r,int L,int R){
	if(L==R){
		for(int i=l;i<=r;++i) Ans[q[i].id]=L;
		return;
	}
	int mid=(L+R)>>1;
	calc(l,r,L,mid);
	int ta=l,tb=r;
	for(int i=l;i<=r;++i)
		if(q[i].cnt>=q[i].k) tmp[ta++]=q[i];
		else q[i].k-=q[i].cnt,tmp[tb--]=q[i];
	for(int i=l;i<=r;++i) q[i]=tmp[i];
	if(ta!=l) slove(l,ta-1,L,mid);
	if(tb!=r) slove(tb+1,r,mid+1,R);
}

int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i) A[A[i].id=i].x=read();
	sort(A+1,A+n+1);
	for(int i=1;i<=m;++i) q[q[i].id=i].x=read(),q[i].y=read(),q[i].k=read();
	slove(1,m,-Inf,Inf);
	for(int i=1;i<=m;++i) printf("%d\n",Ans[i]);
	return 0;
}

 

posted @ 2018-05-17 20:04  void_f  阅读(83)  评论(0编辑  收藏  举报