poj 2104

整体二分 

求区间第k大  

和快速排序差不多           递归的 

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<set>
#include<string>
#include<map>

using namespace std;
typedef long long LL;

#define inf 1e9
#define MAXN 100010
struct node
{
    int x,num;
}a[MAXN];
bool cmp(node a,node b)
{
    return a.x<b.x;
}
struct node1
{
    int x,y,k,num,cnt;
}q[MAXN],b[MAXN];
int sum[MAXN],ans[MAXN];
int n,m;

void calc(int ll,int rr,int rawl,int mid)
{
    int L=1,R=n+1,MID;
    while(L<R)
    {
        MID=(L+R)>>1;
        if(a[MID].x >= rawl)
            R = MID;
        else
            L = MID + 1;
    }
    for(int i=R;i<=n&&a[i].x<=mid;i++)
        for(int j = a[i].num; j <= n;j += (j & -j))
            ++sum[j];
    for(int i=ll;i<=rr;i++)
    {
        q[i].cnt=0;
        for(int j = q[i].y;j;j -= (j & -j))
            q[i].cnt += sum[j];
        for(int j = q[i].x - 1;j;j -= (j & -j))
            q[i].cnt -= sum[j];
    }
    for(int i = R; i <= n && a[i].x <= mid; i++)
        for(int j = a[i].num; j <= n; j += (j & -j))
            sum[j]--;

}

void divide(int ll, int rr, int rawL, int rawR)
{
    if(rawL == rawR)
    {
        for(int i = ll ; i <= rr ; i++)
            ans[q[i].num] = rawR;
        return ;
    }
    int mid = (rawL + rawR) >> 1;
    calc(ll, rr, rawL, mid);
    int now1,now2;
    now1=ll;
    now2=rr;
    for(int i = ll; i<=rr ; i++)
    {
        if(q[i].cnt >= q[i].k)
            b[now1++] = q[i];
        else
        {
            q[i].k -= q[i].cnt;
            b[now2--] = q[i];
        }
    }
    for(int i = ll; i <= rr; i++)
        q[i] = b[i];
    if(now1 != ll)
        divide(ll, now1 - 1, rawL, mid);
    if(now2 != rr)
        divide(now2 + 1, rr, mid + 1,rawR);
}

int main()
{

    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].x);
        a[i].num=i;
    }
    a[n+1].x=2e9;
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].k);
        q[i].num=i;
    }
    divide(1,m,-inf,inf);
    for(int i=1;i<=m;i++)
        printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/cherryMJY/p/6441320.html