hdu 4251 划分树入门题

来源:互联网 发布:如何复制淘宝上的图片 编辑:程序博客网 时间:2024/05/21 19:31

题意:

给n个数字的数组,m个操作,操作输入fr,to。

每次操作求fr,to范围内的中位数。


解析:

把求区间的第k大数转换成了中位数。

中位数是 第 ((to - fr) >> 1) + 1 大数。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <set>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int maxn = 1e5 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int tree[30][maxn];     //表示每层每个位置的值int sorted[maxn];       //排完序的数int toleft[30][maxn];   //toleft[p][i]表示第p层从1到i有多少个数在左边void build(int l, int r, int dep){    if (l == r)        return;    int mi = (l + r) >> 1;    int same = mi - l + 1;          //等于中位数的数字个数    for (int i = l; i <= r; i++)    {        if (tree[dep][i] < sorted[mi])        {            same--;        }    }    int lpos = l;    int rpos = mi + 1;    for (int i = l; i <= r; i++)    {        if (tree[dep][i] < sorted[mi])//比中位数小        {            tree[dep + 1][lpos++] = tree[dep][i];        }        else if (tree[dep][i] == sorted[mi] && same > 0)        {            tree[dep + 1][lpos++] = tree[dep][i];            same--;        }        else                          //比中位数大        {            tree[dep + 1][rpos++] = tree[dep][i];        }        toleft[dep][i] = toleft[dep][l - 1] + lpos - l; // - l  不是减一    }    build(l, mi, dep + 1);    build(mi + 1, r, dep + 1);}//查询区间第k大数int query(int L, int R, int l, int r, int dep, int k){    if (l == r)        return tree[dep][l];    int mi = (L + R) >> 1;    int cnt = toleft[dep][r] - toleft[dep][l - 1];    if (k <= cnt)    {        int nextl = L + toleft[dep][l - 1] - toleft[dep][L - 1];        int nextr = nextl + cnt - 1;        return query(L, mi, nextl, nextr, dep + 1, k);    }    else    {        int nextr = r + toleft[dep][R] - toleft[dep][r];        int nextl = nextr - (r - l - cnt);        return query(mi + 1, R, nextl, nextr, dep + 1, k - cnt);    }}int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);    #endif // LOCAL    int n, m;    int ca = 1;    while (~scanf("%d", &n))    {        memset(tree, 0, sizeof(tree));        memset(toleft, 0, sizeof(toleft));        for (int i = 1; i <= n; i++)//start from 1        {            scanf("%d", &tree[0][i]);            sorted[i] = tree[0][i];        }        sort(sorted + 1, sorted + n + 1);        build(1, n, 0);        scanf("%d", &m);        printf("Case %d:\n", ca++);        while (m--)        {            int fr, to;            scanf("%d%d", &fr, &to);            printf("%d\n", query(1, n, fr, to, 0, ((to - fr) >> 1) + 1));        }    }    return 0;}


0 0
原创粉丝点击