poj2104(主席树。k_th number)

src : http://poj.org/problem?id=2104

ac代码:

#include <bits/stdc++.h>
using namespace std;
#define per(i,a,b) for(int i=a;i<=b;i++)
#define MP make_pair
typedef pair<int,int> PII;
typedef vector<int> VI;
const int inf =0x3f3f3f;
#define siz 100005
int n,m,totn,a[siz],b[siz],Nnum=0,root[siz];//b是离散化的点
struct node
{
    int lc,rc,s;
}Node[siz*20];
void Insert(int l,int r,int pre,int &now,int pos)
{
    now=++Nnum;
    Node[now]=Node[pre];
    Node[now].s++;//区间内的个数+1
    if(l==r)return;
    int mid=(l+r)>>1;
    if(pos<=mid)Insert(l,mid,Node[pre].lc,Node[now].lc,pos);
    else Insert(mid+1,r,Node[pre].rc,Node[now].rc,pos);
}
int query(int l,int r,int x,int y,int k)//[x,y] k_th 这个函数里的xy已经是xy对应的root了!
{
    if(l==r)return l;
    int mid=(l+r>>1);
    int sum=Node[Node[y].lc].s-Node[Node[x].lc].s;//用于判断第k个在左子树还是右子树
    //sum就表示[x,y]阶段内[l,r]的左子树的个数
    if(sum>=k)query(l,mid,Node[x].lc,Node[y].lc,k);
    else query(mid+1,r,Node[x].rc,Node[y].rc,k-sum);
}
int main()
{
    totn=0;
    scanf("%d %d",&n,&m);
    per(i,1,n){scanf("%d",&a[i]);b[i]=a[i];}
    sort(b+1,b+1+n);
    totn=unique(b+1,b+1+n)-b-1;
    cerr<<"tot:"<<totn<<endl;//
    per(i,1,n)
        Insert(1,totn,root[i-1],root[i],lower_bound(b+1,b+1+n,a[i])-b);
    int x,y,k;
    for(int i=1;i<=m;i++){
        scanf("%d %d %d",&x,&y,&k);
        printf("%d\n",b[query(1,totn,root[x-1],root[y],k)]);
    }

    return 0;
}

 

posted @ 2018-08-01 12:50  WindFreedom  阅读(142)  评论(0编辑  收藏  举报