POJ 2104 K-th Number (划分树)

来源:互联网 发布:会声会影完美卸载软件 编辑:程序博客网 时间:2024/06/06 05:15

~~~题目链接~~~


题目大意:给出n个数,现在要求求出区间中的第k大值


思路:划分树模版



#include <cstdio>#include <algorithm>#define N  100002using namespace std;struct node{    int num[N], val[N];}t[1000];//记录每层的划分int n = 0, m = 0, ans = 0, srt[N];void build_tree(int l, int r, int cur){    int m = (l+(r-l)/2), mid = 0, left_num = 0;    int s1 = l, s2 = m+1, c1 = 0, c2 = 0;//s1为下一层分人左边数开始存的地方, s2为分入右边第开始    if(l == r) return ;    mid = srt[m];    for(int i = l; i<=r; i++) if(t[cur].val[i]<mid) c2++;//共有多少个进入左边的    left_num = m-l+1-c2;//为有多少个值等于mid时可以进左边的    for(int i = l; i<=r; i++)//选出左右边的部分    {        if(i == l) t[cur].num[i] = 0;        else t[cur].num[i] = t[cur].num[i-1];        if(t[cur].val[i]<mid)//小于进入左边        {            t[cur].num[i]++;            t[cur+1].val[s1++] = t[cur].val[i];        }        else if(t[cur].val[i]==mid && c1<left_num)        {            c1++;            t[cur].num[i]++;            t[cur+1].val[s1++] = t[cur].val[i];        }        else            t[cur+1].val[s2++] = t[cur].val[i];    }    build_tree(l, m, cur+1);    build_tree(m+1, r, cur+1);}//okvoid query(int a, int b, int k, int l, int r, int cur){    int m = (l+(r-l)/2);    if(a == b){ans = t[cur].val[a]; return ;}    int x = t[cur].num[a-1], y = t[cur].num[b];    if(a == l) x = 0;    if(y-x>=k)        query(l+x, l+y-1, k, l, m, cur+1);//进入左边进行查询    else    {        k = k-(y-x);        int s1 = a-l-x, s2 = (b-a+1)-(y-x);        if(a == l) s1 = 0;        query(m+1+s1, m+s2+s1, k, m+1, r, cur+1);//进入右边进行查询    }}int main(){    int i = 0, a = 0, b = 0, k = 0;    while(scanf("%d %d", &n, &m) != EOF)    {        for(i = 1; i<=n; i++)        {            scanf("%d", &t[1].val[i]);            srt[i] = t[1].val[i];        }        sort(srt+1, srt+n+1);        build_tree(1, n, 1);        while(m--)        {            scanf("%d %d %d", &a, &b, &k);            query(a, b, k, 1, n, 1);            printf("%d\n", ans);        }    }    return 0;}




原创粉丝点击