D - Mike and distribution
题意:
有两个数列,个数相同,现在选出不超过n/2+1个数列下标,使得在每一个数列中下标的数字之和的二倍大于原数列,输出答案和下标。
思路:
题意是经过化简 的,因为题中并没有说要选择多少个下标,只是一个范围,那么最简单的做法当然是选择越多越好。
方法:思考挑选的个数,明显是大于数列个数的一半的。
先对A数列做一次排序,那么从大到小挑选的时候肯定满足A数列,对于B数列,现选择第一个数字,然后剩下的数字选则大的。若n是偶数,那么再把最后一个数列选择。
其中有贪心的思想,巧妙。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long LL;
struct Node
{
LL a,b;
int pos;
}p[maxn];
int n;
int ans[maxn];
bool cmp(Node a,Node b)
{
if(a.a == b.a)
return a.b > b.b;
return a.a > b.a;
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i = 1;i <= n; i++) {
scanf("%I64d",&p[i].a);
p[i].pos = i;
}
for(int i = 1;i <= n; i++) {
scanf("%I64d",&p[i].b);
}
sort(p+1,p+1+n,cmp);
int pos = 1;
int ansn = n/2+1;
ans[1] = p[1].pos;
for(int i = 2;i+1 <= n; i += 2) {
if(p[i].b > p[i+1].b) ans[++pos] = p[i].pos;
else ans[++pos] = p[i+1].pos;
}
if(!(n%2))
ans[++pos] = p[n].pos;
printf("%d\n",ansn);
printf("%d",ans[1]);
for(int i = 2;i <= ansn; i++) {
printf(" %d",ans[i]);
}
printf("\n");
return 0;
}