Codeforces Round #410 (Div. 2) D. Mike and distribution (贪心)

版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/81907776

原题地址:http://codeforces.com/contest/798/problem/D

题意:有 2 个序列,长度都是 n ,你需要选出 [ n 2 ] + 1 个下标,使得这些下标对应的元素在 a , b 任何一个序列中相加的和乘 2 ,都大于该序列所有元素的和.

思路:
首先,对于题目要求的选择元素之和两倍大与所有元素之和,我们可以转化为选择元素之和大于剩下的。然后我们可以将下标按照a从大到小排序。然后选择第一个,之后每两个一组,选择b大的一个,如果n是偶数再选择最后一个。

至于这样写的正确性:首先对于数组b,每一组选择的都是大的,而且还有多选的,所以一定比剩下的大。对于数组a,从第一个开始看,当前选择的,一定比下一组剩下的a大。所以这样贪心就一定正确。

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 998244353;
int n;
struct node {
    int num, id;
} a[maxn];
int b[maxn];
bool cmp(node a, node b) {
    return a.num > b.num;
}
vector<int>v;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i].num);
        a[i].id = i;
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d", &b[i]);
    }
    sort(a+1,a+1+n,cmp);
    v.push_back(a[1].id);
    for (int i = 2; i <= n; i += 2) {
        if (i == n) {
            v.push_back(a[i].id);
            break;
        }
        if(b[a[i].id]>b[a[i+1].id]) v.push_back(a[i].id);
        else v.push_back(a[i+1].id);
    }
    printf("%d\n",v.size());
    for(int i=0;i<v.size();i++) printf("%d ",v[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81907776