POJ 2985 The k-th Largest Group (树状数组学习)

初识树状数组,确实是一种优美的数据结构,夹杂着很强的数学模型在里面。

http://poj.org/summerschool/1_interval_tree.pdf 这里已经说明的非常清楚。

http://dongxicheng.org/structure/binary_indexed_tree/ 这篇文章说的也是差不多的。

重要的是去思考,为什么树形数组能够行的通,看了下面不难理解:

C1=A1
C2=A1+A2
C3=A3
C4=A1+A2+A3+A4
C5=A5
C6=A5+A6
C7=A7
C8=A1+A2+A3+A4+A5+A6+A7+A8
…………
C16=A1+A2+A3+A4+A5+A6+A7+A8+A9+A10+A11+A12+A13+A14+A15+A16

 

关于这一题,是求第k大数字,树形数组的O(logn)^2算法(还可以再优化到O(logn)),可谓把它的优美程度完美体现

#include <cstdio>
#include <cstdlib>
#include <cstring>

const int MAXN = 200010;
// c[i]树形数组,生成c[i]的数组s[i]表示,大小为i的的集合的个数
// f[i]节点i的父亲节点
// a[i]以节点i为根节点的集合元素个数,初始化为1
int c[MAXN], f[MAXN], a[MAXN];  
int n, m;

int find_set(int x)
{
    int r = x;
    while (r != f[r])
        r = f[r];
    int p = x;
    while (p != r)
    {
        p = f[p];
        f[p] = r;
    }
    return r;
}

inline int low_bit(int x)
{
    return x & (-x);
}

void add(int p, int d)
{
    for (int i = p; i <= n; i += low_bit(i))
        c[i] += d;
}

int sum(int p)
{
    int ans = 0;
    for (int i = p; i > 0; i -= low_bit(i))
        ans += c[i];
    return ans;
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i)
        c[i] = 0, a[i] = 1, f[i] = i;

    add(1, n);
    int num = n;
    for (int i = 1; i <= m; ++i)
    {
        int temp;
        scanf("%d", &temp);
        if (!temp)
        {
            int x, y;
            scanf("%d %d", &x, &y);
            x = find_set(x);
            y = find_set(y);
            if (x == y)
                continue;
            add(a[x], -1);
            add(a[y], -1);
            add(a[x] + a[y], 1);
            f[x] = y;
            a[y] += a[x];
            --num;
        }
        else
        {
            int k;
            scanf("%d", &k);
            k = num - k + 1;
            int l = 1, r = n;
            while (l <= r)
            {
                int mid = (l + r) >> 1;
                if (k <= sum(mid))
                    r = mid - 1;
                else 
                    l = mid + 1;
            }
            printf("%d\n", l);
        }
    }
    return 0;
}
posted @ 2012-11-09 21:35  kedebug  阅读(707)  评论(0编辑  收藏  举报