hrbust 1041(并查集)

题意:长度为n的Chocolate,为n份1,2,3...n,每操作一次假如是[i,j],则i到j的(包括i, 和j)被买完。

要求输出每次操作能买的Chocolate有多少份。

例如;

6 4

1 2//可以买1,2 两份。

4 4//可以买4一份。

1 3//因为1,2已经买过了,只剩下3了,所以只能买3一份。

1 4//1,2,3,4都买过了。所以输出0。

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

const int maxn = 10000001;
int find[maxn];//find[i]存储的是前一步指向的。

int cal(int i)
{
    return i==find[i] ? i : find[i] = cal(find[i]);//并查集
}
void nextcal(int i, int j)//小的指向大的
{
    int x = cal(i);
    int y = cal(j);
    if (x != y)
    {
        if (x > y)
        {
            find[y] = x;
        }
        else
        {
            find[x] = y;
        }
    }
}

int main(void)
{
    int t, n, m;
    int a, b, i;
    int res;
    scanf("%d", &t);

    while (t--)
    {
        scanf("%d%d", &n, &m);
        for (i=1; i<=n+1; i++)
        {
            find[i] = i;
        }
        while (m--)
        {
            res = 0;
            scanf("%d%d", &a, &b);
            for (i=a; i<=b;)
            {
                if ( i== find[i])
                {
                    //printf("cal(%d)==%d, find[%d]==%d\n",i,  cal(i), i, find[i]);
                    res++;
                    nextcal(i, b+1);
                    //printf("cal(%d)==%d, find[%d]==%d\n",i,  cal(i), i, find[i]);
                    i++;
                }
                else
                {
                    //printf("cal(%d)==%d, find[%d]==%d\n",i,  cal(i), i, find[i]);
                    i = cal(i);//关键优化,注意不是find[i];
                }
            }
            printf("%d\n", res);
        }
    }
    return 0;
}

 

 

 

posted @ 2013-03-30 11:21  尔滨之夏  阅读(204)  评论(0编辑  收藏  举报