Codeforces 798D

题目链接:http://codeforces.com/problemset/problem/798/D

题目大意:从长度为n的序列A和序列B中分别选出k个下表相同的数要求,设这两个序列中k个数和分别为ta,tb,两个序列总和分别为asum,bsum。要求ta*2>asum&&tb*2>bsum,k<=n/2+1.

解题思路:首先,肯定要选n/2+1的吧。我们把序列A当成第一层,序列B当成第二层。第一层:按从大到小严格排好。在第二层上:每两个取大的那一个,那最后的和肯定>=总和的一半,而且再加上第一个,所以所选数的和和>总和的一半。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=1e6+5;
 6 
 7 struct node {
 8     int a;
 9     int b;
10     int num;
11 }t[N];
12 
13 bool cmp(node x,node y){
14     return x.a>y.a;//第一层按从大到小排好
15 }
16 
17 int main(){
18     ios::sync_with_stdio(false);
19     int n;
20     cin>>n;
21     for(int i=1;i<=n;i++){
22         cin>>t[i].a;
23     }
24     for(int i=1;i<=n;i++){
25         cin>>t[i].b;
26         t[i].num=i;
27     }
28     sort(t+1,t+1+n,cmp);
29     cout<<n/2+1<<endl;
30     cout<<t[1].num<<" ";
31     for(int i=2;i<=n;i+=2){
32         cout<<(t[i].b>t[i+1].b?t[i].num:t[i+1].num)<<" ";//两两取较大的那个 
33     }
34     cout<<endl;
35     return 0;
36 } 

还有一种利用random_shuffle随机排列来写的,就是每次排好都选前k个,总会选到符合条件的答案,玄学。。。。:

#include<iostream>
#include<algorithm>
#include<cstdlib> 
#include<time.h>
using namespace std;
const int N=1e6+5;
typedef long long LL;
struct node {
    int a;
    int b;
    int num;
}t[N];

int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    LL asum=0,bsum=0;
    for(int i=1;i<=n;i++){
        cin>>t[i].a;
        asum+=t[i].a;
    }
    for(int i=1;i<=n;i++){
        cin>>t[i].b;
        t[i].num=i;
        bsum+=t[i].b;
    }
    cout<<n/2+1<<endl;
    srand(time(NULL));
    while (1) {
        random_shuffle(t+1, t+n+1);
        LL ta=0,tb=0;
        for(int i=1;i<=n/2+1;i++){
            ta+=t[i].a;
            tb+=t[i].b;
        } 
        if (2*ta>asum&&2*tb>bsum) {
            for(int i=1;i<=n/2+1;i++){
                cout<<t[i].num<<" ";
            }
            cout<<endl;
            return 0;
        }
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/fu3638/p/6838442.html