POJ 2104 K-th Number

莫队算法+离散化+树状数组+二分

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
using namespace std;

const int maxn=100000+10;
int n,m;
int a[maxn],b[maxn],lsh[maxn],pos[maxn];

struct X
{
    int l,r,k,id;
}s[5000+10];
int Ans[5000+10];
int L,R,ans;

bool cmp(const X&a, const X&b)
{
    if (pos[a.l] == pos[b.l]) return a.r < b.r;
    return a.l < b.l;
}

int c[maxn];

int lowbit(int x) {return x&(-x);}

int getsum(int pos)
{
    int res=0;
    for(int i=pos;i>0;i=i-lowbit(i)) res=res+c[i];
    return res;
}

void update(int pos,int val)
{
    for(int i=pos;i<=n;i=i+lowbit(i)) c[i]=c[i]+val;
}

int get(int num)
{
    int l=1,r=n;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(lsh[mid]>num) r=mid-1;
        else if(lsh[mid]==num) return mid;
        else l=mid+1;
    }
}

void LSH()
{
    for(int i=1;i<=n;i++) lsh[i]=a[i];
    sort(lsh+1,lsh+1+n);
    for(int i=1;i<=n;i++) b[i]=get(a[i]);
}

int f(int num)
{
    int l=1,r=n,res;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(getsum(mid)>num) r=mid-1;
        else if(getsum(mid)==num) res=mid,r=mid-1;
        else l=mid+1;
    }
    return res;
}

int main()
{
    scanf("%d%d",&n,&m);
    int sz=sqrt(1.0*n);
    for(int i=1;i<=n;i++){scanf("%d",&a[i]);pos[i]=i/sz;}
    LSH();
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&s[i].l,&s[i].r,&s[i].k);
        s[i].id=i;
    }
    sort(s+1,s+1+m,cmp);
    for(int i=s[1].l;i<=s[1].r;i++) update(b[i],1);
    Ans[s[1].id]=lsh[f(s[1].k)];
    L=s[1].l; R=s[1].r;
    for(int i=2;i<=m;i++)
    {
        while(L<s[i].l) update(b[L],-1),L++;
        while(L>s[i].l) L--,update(b[L],1);
        while(R<s[i].r) R++,update(b[R],1);
        while(R>s[i].r) update(b[R],-1),R--;
        Ans[s[i].id]=lsh[f(s[i].k)];
    }
    for(int i=1;i<=m;i++) printf("%d\n",Ans[i]);
    return 0;
}

 

posted @ 2016-05-05 08:42  Fighting_Heart  阅读(131)  评论(0编辑  收藏  举报