BZOJ2223 PATULJCI COCI2009_CONTSET3

背景:

输入:
BZOJ2223 PATULJCI COCI2009_CONTSET3_第1张图片
输出:
输出
大意:
白雪公主和N个小矮人住在森林里。每天早上,矮人们排成一队出去挖矿的路上,白雪公主就负责给他们拍照,并把这些照片传到社交网络上去。
白雪每次都会拍很多照片,她要从中选出一些完美的照片。小矮人们都戴着不同颜色的
帽子。如果照片上小矮人们有一半以上人戴着相同颜色的帽子,则这张照片就算是美丽的。
也就是说,如果照片上有K个人,如果有多于K/2的人带着相同颜色的帽子,则这张照片就是美丽的。
现在,写一个程序来检测相片集M是不是美丽的,并且判断出美丽照片上,哪种是主要的颜色。

思路:我们可以考虑一个随机算法,在区间 [A,B] 中任意找到一个值,如果有照片是pretty的,那么找一次找到的可能性就是 >12 的。所以只要我们枚举到20次那么我们错误的概率就会远小于 220 就很不容易错了。那么我们可以想想怎么判断是否是pretty的。
首先,我们可以以颜色为第一关键字,小矮人的位置为第二关键字排个序(颜色可以升序,可以降序,主要是为了把颜色集中,小矮人的位置按照升序)。然后我们便可以用二分查找找到某个区间内的某种颜色的小矮人的数量了(用大于这个 (颜色,位置) 的第一个减去大于等于 大于等于的第一个,便是数量了)。
然后根据随机的思想,我们就可以完成这道题了。

附上代码:

#include<cstdio>
#include<algorithm>
#define PII pair<int, int>
const int S = 17;      //控制随机的次数
#define MAXN 300005
using namespace std;
int a[MAXN];
PII b[MAXN];
int n, m, q;
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d", &a[i]);
        b[i] = PII(a[i], i);
    }
    sort(b + 1, b + n + 1);
    int t1, t2;
    scanf("%d", &q);
    while(q --)
    {
        scanf("%d%d", &t1, &t2);
        int i, x, cnt;
        for(i = 1; i < S; i ++)
        {
            x = a[t1 + rand()%(t2 - t1 + 1)];
            cnt = upper_bound(b+1, b + n +1, PII(x, t2)) - lower_bound(b + 1, b + n + 1, PII(x, t1));     //找有几个x颜色的在这个区间内。
            if(cnt * 2 > (t2 - t1 + 1))
                break;
        }
        if(i == S)           //没找到
            puts("no");
        else printf("yes %d\n", x);
    }
    return 0;
}

你可能感兴趣的:(bzoj,coci,随机化)