zoukankan      html  css  js  c++  java
  • [CF798D] Mike and distribution(贪心,鸽笼原理,随机)

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

    题意:两个数列a、b,分别有n个数。希望选出下标相同的尽可能少的数字,使得它们分别的和为两个数列中数字分别总和的一半,尽可能少指的是≤  。只要在这个范围内,都算符合条件。

    不妨就认为题目是要选个数字,使得满足条件。题目要求二倍的选中的数字-原数字总和>0,同时减掉一倍选中的数字和,问题转换成了选个数,使得选中的数的总和比剩下的数的综合大。

    由于选了,可以先给a排序,记下a的id和val。a中的数必然选择最大的那个,这样能保证接下来选择能同时满足:a中选的数比另一个数大;从a(i).id和a(i+1).id选b较大的一个,这样能保证b中的数字一个大的比一个小的大,选其中大的那个数,总和当然比剩下的大。稍微想一下觉得这个和鸽巢原理有关系。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long LL;
     5 typedef struct X {
     6     int id, val;
     7 }X;
     8 const int maxn = 100100;
     9 int n, m;
    10 X a[maxn], b[maxn];
    11 
    12 int main() {
    13     // freopen("in", "r", stdin);
    14     while(~scanf("%d", &n)) {
    15         for(int i = 1; i <= n; i++) {
    16             scanf("%d", &a[i].val);
    17             a[i].id = i;
    18         }
    19         for(int i = 1; i <= n; i++) {
    20             scanf("%d", &b[i].val);
    21             b[i].id = i;
    22         }
    23         m = n / 2 + 1;
    24         sort(a+1, a+n+1, [](X a,X b){return a.val>b.val;});
    25         int pa = n, pb = n;
    26         vector<int> ret;
    27         ret.push_back(a[1].id);
    28         for(int i = 2; i <= n; i+=2) {
    29             if(i + 1 <= n && b[a[i].id].val < b[a[i+1].id].val) ret.push_back(a[i+1].id);
    30             else ret.push_back(a[i].id);
    31         }
    32         printf("%d
    ", m);
    33         for(int i = 0; i < ret.size(); i++) {
    34             printf("%d%c", ret[i], i==ret.size()-1?'
    ':' ');
    35         }
    36     }
    37     return 0;
    38 }

    看讨论版还有用random随出来的,感觉O(能过)。。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long LL;
     5 const int maxn = 100100;
     6 int n, m, a[maxn], b[maxn], p[maxn];
     7 LL sa, sb;
     8 
     9 bool ok() {
    10     LL ta = 0, tb = 0;
    11     for (int i = 1; i <= m; ++i) {
    12         ta += 2LL * a[p[i]], tb += 2LL * b[p[i]];
    13         if (ta > sa && tb > sb) return 1;
    14     }
    15     return 0;
    16 }
    17 
    18 int main() {
    19     // freopen("in", "r", stdin);
    20     while(~scanf("%d", &n)) {
    21         sa = sb = 0;
    22         for (int i = 1; i <= n; i++) {
    23             scanf("%d", &a[i]);
    24             sa += a[i]; p[i] = i;
    25         }
    26         for (int i = 1; i <= n; i++) {
    27             scanf("%d", &b[i]);
    28             sb += b[i];
    29         }
    30         m = n / 2 + 1;
    31         while (!ok()) random_shuffle(p + 1, p + 1 + n);
    32         printf("%d
    ", m);
    33         for (int i = 1; i <= m; i++) printf("%d%c", p[i], i==m?'
    ':' ');
    34     }
    35     return 0;
    36 }
  • 相关阅读:
    基于Hadoop的改进Apriori算法
    iOS 访问URL转码
    第一次进入应用图片轮播效果
    购物篮模型&Apriori算法
    Ionicons的使用
    如何在 Eclipse 中使用命令行
    Eclipse输入命令行参数
    CHAR,TCHAR,WCHAR 三者的区别与转换
    函数名、变量前后的_(一个下划线)、__(两个下划线)分别有什么用
    java爬虫简单实现
  • 原文地址:https://www.cnblogs.com/kirai/p/6873243.html
Copyright © 2011-2022 走看看