版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/81907776
原题地址:http://codeforces.com/contest/798/problem/D
题意:有 个序列,长度都是 ,你需要选出 个下标,使得这些下标对应的元素在 任何一个序列中相加的和乘 ,都大于该序列所有元素的和.
思路:
首先,对于题目要求的选择元素之和两倍大与所有元素之和,我们可以转化为选择元素之和大于剩下的。然后我们可以将下标按照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;
}