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;
}