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;

}

你可能感兴趣的:(group)