noip模拟赛 集合

分析:感觉像是贪心,再看数据范围这么大,肯定是贪心没错.但是要怎么贪呢?主要的思想是让每次往上加的数尽量多,肯定要先把0分裂,如果能正好一起跳到最终状态就好.举个例子:5,3,2,1,最大值比次大值大2,所以肯定有一个0先跳两下,另外一个0分裂,等到第一个0跳了两下后再接着跳,这样手推感觉有点复杂,于是就想,5,3,2,1这个状态从哪个状态转移过来呢?4,2,1,0,再往回转移3,1,0,0,两个0肯定是由一个0分裂而来的,再上一个状态是2,0,0,不断的合并,直到只剩下一个0.那么贪心的方法就出来了:倒着贪心.

      正着想构造不出来方法,可以倒着从已知状态来得到.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n, a[1000010], cnt[1000010], tot, ans, maxx;

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        cnt[a[i]]++;
        maxx = max(maxx, a[i]);
    }
    tot = cnt[0];
    for (int i = 1; i <= maxx; i++)
    {
        ans++;
        tot = (tot + 1) / 2;
        tot += cnt[i];
    }
    while (tot > 1)
    {
        tot = (tot + 1) / 2;
        ans++;
    }
    printf("%d\n", ans);

    return 0;
}

 

posted @ 2017-11-02 13:54  zbtrs  阅读(186)  评论(0编辑  收藏  举报