主席书 POJ2104

2018-07-22 20:35:11

终于有了自己的主席书板子 先保存下来 明天写总结 挖坑++

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>

using namespace std;

const int maxn = 1e5+10;
int n , m;
int cnt;
struct node
{
    int L , R;   ///该节点的左右节点
    int sum;    ///该节点所管辖区域内数字的个数
    node()
    {
        sum = 0;
    }
} Tree[maxn*20];

struct value
{
    int x;
    int id;
} val[maxn]; ///离散化

bool cmp(value a, value b)
{
    return a.x < b.x;
}

int root[maxn];  ///多颗线段树的根节点
int rank[maxn];  ///原数组离散之后的数组

void init()
{
    cnt = 1;
    root[0] =0;
    Tree[0].L = Tree[0].R = Tree[0].sum = 0;     ///初始化建立一个空节点
}

void input()
{
    for(int i=1; i<=n; i++)
    {
        scanf("%d" , &val[i].x);
        val[i].id = i;
    }
}

void update(int num , int &rt , int l , int r)
{
    Tree[cnt++] = Tree[rt];
    rt = cnt-1;
    Tree[rt].sum++;       ///增加了一个数字
    if(l == r)
        return;
    int mid = (l+r)/2;
    if(num <= mid) update(num , Tree[rt].L , l , mid);
    else update(num , Tree[rt].R , mid+1 , r);
}

int query(int i , int j , int k , int l , int r)
{
    if(l == r)
        return l;
    int d = Tree[Tree[j].L].sum-Tree[Tree[i].L].sum;
    int mid = (l+r)/2;
    if(k <= d) return query(Tree[i].L , Tree[j].L , k , l , mid);
    else  return query(Tree[i].R , Tree[j].R , k-d , mid+1 , r);
}

void solve()
{
    int l , r , k;
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%d" , &l , &r , &k);
        printf("%d\n" , val[query(root[l-1] , root[r] , k , 1 , n)].x);
    }
}

int main()
{
    while( scanf("%d%d" , &n , &m) != EOF )
    {
        input();
        sort(val+1 , val+1+n , cmp);
        for(int i=1; i<=n; i++)
        {
            rank[val[i].id] = i;
        }                                     ///离散化结束
        init();
        for(int i=1; i<=n; i++)
        {
            root[i] = root[i-1];
            update(rank[i] , root[i] , 1 , n);
        }
        solve();
    }


    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Flower-Z/p/9351322.html