CF-Codeforces Round #410 (Div. 2)-D-Mike and distribution

来源:互联网 发布:编程计算xyz yzz 编辑:程序博客网 时间:2024/05/29 13:47

ACM模版

描述

描述

题解

这个题当时我没看懂题,所以没做,后续补题时学到了很多东西~~~好题!

题意大概是,从 A[] 和 B[] 中对应位置分别取不超过n2+1 个数,使分别对于 A[] 和 B[] 来说,这些数之和的二倍大于该数组和,也就是说子集的两倍大于数组和,那么等价于所取的数之和大于未取的数之和,所以,这里自然是取数越多越好,最多 n2+1个。

这里由于结果不唯一,所以这是一个特判题。这样也就催生出了一种玄学的解法(代码 One),通过随机乱序原数组,然后判断前 n2+1 个数的和是否满足题意,不满足继续乱序,一直到碰应了结果就输出,GG。这个有些许猴子排序的恶搞趣味,但是你没有看错,这里能够 AC。据我猜测这个之所以可行是因为可行解十分多,所以他乱序碰到答案的可能性比较高,如果对于可行解不多的题,那么这就是贴脸草题,有些考验脸了。

当然,还有比较客观的解法(代码 Two),先根据 A[] 对 pos 排序,然后将最大的入 ans,接着每两个进行一次判断,看哪个 B[] 大,大的入 ans,这样遍历一遍后就是结果了。这里需要强调的一点是必须先将最大的入 ans,不然无法保证 A 的合法性,只有先将最大的入了 ans,才能保证下次未选取的数一定小于上一次选取的数,例如,1,4,6,8,9,我们先将 9 入 ans,然我们不管在 (6,8) 中选取哪个,那个未被选取的都一定小于 9,接着在 (1,4) 中不管选哪个,那个未被选取的都要比上一个选取的数(6 或 8)小,这就可以保证 A 的合法性。

另外,这个客观的解法需要定义一个三元结构体,分别存储 a, b, pos,在网上看到了一个我没有用过的数据结构来直接搞,十分方便,叫做元组,<tuple>,类似于结构体,十分强大,这里我也提供一下利用元组的解法(代码 Three)。

代码

One:

#include <iostream>#include <algorithm>#include <ctime>using namespace std;typedef long long ll;const int MAXN = 1e5 + 10;int n;int pos[MAXN];int a[MAXN], b[MAXN];ll sumA, sumB;int main(int argc, char const *argv[]){    scanf("%d", &n);    for (int i = 0; i < n; i++)    {        scanf("%d", a + i);        sumA += a[i];        a[i] <<= 1;        pos[i] = i;    }    for (int i = 0; i < n; i++)    {        scanf("%d", b + i);        sumB += b[i];        b[i] <<= 1;    }    int mid = n / 2 + 1;    srand((int)time(0));    while (1)    {        ll s1 = 0, s2 = 0;        random_shuffle(pos , pos + n);        for (int i = 0; i < mid; i++)        {            s1 += a[pos[i]];            s2 += b[pos[i]];        }        if (s1 > sumA && s2 > sumB)        {            printf("%d\n%d", mid, pos[0] + 1);            for (int i = 1; i < mid; i++)            {                printf(" %d", pos[i] + 1);            }            puts("");            return 0;        }    }    return 0;}

Two:

#include <iostream>#include <algorithm>#include <vector>using namespace std;const int MAXN = 1e5 + 5;struct abpos{    int a;    int b;    int pos;};abpos c[MAXN];vector<int> ans;int n;int a[MAXN], b[MAXN];bool cmp(abpos a, abpos b){    return a.a < b.a;}int main(){    cin >> n;    for (int i = 1; i <= n; i++)    {        cin >> a[i];    }    for (int i = 1; i <= n; i++)    {        cin >> b[i];    }    c[0].a = c[0].b = c[0].pos = 0;    for (int i = 1; i <= n; i++)    {        c[i].a = a[i];        c[i].b = b[i];        c[i].pos = i;    }    sort(c + 1, c + n + 1, cmp);    ans.push_back(c[n].pos);    for (int i = n - 1; i >= 1; i -= 2)    {        if (c[i].b > c[i - 1].b)        {            ans.push_back(c[i].pos);        }        else        {            ans.push_back(c[i - 1].pos);        }    }    cout << ans.size() << endl;    for (int i = 0; i < ans.size(); i++)    {        cout << ans[i] << ' ';    }    return 0;}

Three:

#include <iostream>#include <algorithm>#include <vector>#include <tuple>using namespace std;typedef tuple<int, int, int> tp;const int MAXN = 1e5 + 5;tp tpThree[MAXN];vector<int> ans;int n;int a[MAXN], b[MAXN];int main(){    cin >> n;    for (int i = 1; i <= n; i++)    {        cin >> a[i];    }    for (int i = 1; i <= n; i++)    {        cin >> b[i];    }    for (int i = 1; i <= n; i++)    {        tpThree[i] = tp(a[i], b[i], i);    }    tpThree[0] = tp(0, 0, 0);    sort(tpThree + 1, tpThree + n + 1);    int pos;    tie(ignore, ignore, pos) = tpThree[n];    ans.push_back(pos);    int y, y_, pos_;    for (int i = n - 1; i >= 1; i -= 2)    {        tie(ignore, y, pos) = tpThree[i];        tie(ignore, y_, pos_) = tpThree[i - 1];        if (y > y_)        {            ans.push_back(pos);        }        else        {            ans.push_back(pos_);        }    }    cout << ans.size() << endl;    for (int i = 0; i < ans.size(); i++)    {        cout << ans[i] << ' ';    }    return 0;}
1 0
原创粉丝点击