区间第k大(poj 2104)

来源:互联网 发布:nvidia控制面板优化 编辑:程序博客网 时间:2024/04/28 11:19

区间第k大有很多种求法,最近在刷线段树,所以用线段树结合STL写了一个。

线段树的建立类似与归并树:

    

可以通过线段数快速求得某个区间大于或者小于某个数的数的个数。

然后二分答案,直到结果为k为止。

poj 2104就是一道求区间第k大的题目

下面我的代码:

#include <cstdio>#include <algorithm>#include <iostream>#include <vector>#define maxn 1000005using namespace std;vector <int> dat[maxn*2];int num[maxn],A[maxn];int build (int o,int L,int R){  if (L==R){    dat[o].push_back(num[L]);  }  else {    int M=L+(R-L)/2;    build (o*2,L,M);    build (o*2+1,M+1,R);    dat[o].resize(R-L+1);    merge(dat[o*2].begin(),dat[o*2].end(),dat[o*2+1].begin(),dat[o*2+1].end(),dat[o].begin());  }  return 0;}int c,y1,y2,x;int query (int o,int L,int R){    if (y1<=L&&y2>=R){      c+=upper_bound(dat[o].begin(),dat[o].end(),x)-dat[o].begin();    }    else {      int M=L+(R-L)/2;      if (y1<=M) query(o*2,L,M);      if (y2>M) query(o*2+1,M+1,R);    }    return 0;}int n,m;int solve(int l,int r,int k){  int lb=1,rb=n;  y1=l,y2=r;  while (rb>lb){    int Mid=lb+(rb-lb)/2;    x=A[Mid];    c=0;    query(1,1,n);    if (c>=k) rb=Mid;    else lb=Mid+1;    //cout<<c<<" "<<x<<endl;  }  printf("%d\n",A[rb]);}int main (){  while (~scanf("%d%d",&n,&m)){    for (int i=1;i<=n;i++){      scanf("%d",&num[i]);      A[i]=num[i];    }    build(1,1,n);    sort(A+1,A+n+1);    for (int i=0;i<m;i++){       int l,r,k;       scanf("%d%d%d",&l,&r,&k);       solve(l,r,k);    }  }  return 0;}


0 0
原创粉丝点击