zoukankan      html  css  js  c++  java
  • D. Mike and distribution 首先学习了一个玄学的东西

    http://codeforces.com/contest/798/problem/D

    D. Mike and distribution
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Mike has always been thinking about the harshness of social inequality. He's so obsessed with it that sometimes it even affects him while solving problems. At the moment, Mike has two sequences of positive integersA = [a1, a2, ..., an] and B = [b1, b2, ..., bn] of length n each which he uses to ask people some quite peculiar questions.

    To test you on how good are you at spotting inequality in life, he wants you to find an "unfair" subset of the original sequence. To be more precise, he wants you to select k numbers P = [p1, p2, ..., pk] such that 1 ≤ pi ≤ n for1 ≤ i ≤ k and elements in P are distinct. Sequence P will represent indices of elements that you'll select from both sequences. He calls such a subset P "unfair" if and only if the following conditions are satisfied: 2·(ap1 + ... + apk)is greater than the sum of all elements from sequence A, and 2·(bp1 + ... + bpk) is greater than the sum of all elements from the sequence B. Also, k should be smaller or equal to  because it will be to easy to find sequence P if he allowed you to select too many elements!

    Mike guarantees you that a solution will always exist given the conditions described above, so please help him satisfy his curiosity!

    Input

    The first line contains integer n (1 ≤ n ≤ 105) — the number of elements in the sequences.

    On the second line there are n space-separated integers a1, ..., an (1 ≤ ai ≤ 109) — elements of sequence A.

    On the third line there are also n space-separated integers b1, ..., bn (1 ≤ bi ≤ 109) — elements of sequence B.

    Output

    On the first line output an integer k which represents the size of the found subset. k should be less or equal to .

    On the next line print k integers p1, p2, ..., pk (1 ≤ pi ≤ n) — the elements of sequence P. You can print the numbers in any order you want. Elements in sequence P should be distinct.

    Example
    input
    5
    8 7 4 8 3
    4 2 5 3 7
    output
    3
    1 4 5

     用了一个叫random_shuffle的东西,每次都乱选,然后暴力前k个。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 1e5 + 20;
    int a[maxn], b[maxn];
    
    bool in[maxn];
    LL sumA, sumB;
    LL allA, allB;
    int c[maxn];
    int n, en;
    bool ok() {
        LL ta = 0, tb = 0;
        for (int i = 1; i <= en; ++i) {
            ta += 2 * a[c[i]];
            tb += 2 * b[c[i]];
            if (ta > allA && tb > allB) return true;
        }
        return false;
    }
    void work() {
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            allA += a[i];
        }
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &b[i]);
            allB += b[i];
            c[i] = i;
        }
        en = (n) / 2 + 1;
        while (!ok()) {
            random_shuffle(c + 1, c + 1 + n);
    //        for (int i = 1; i <= n; ++i) {
    //            cout << c[i] << " ";
    //        }
    //        cout << endl;
        }
        cout << en<< endl;
        for (int i = 1; i <= en; ++i) {
            printf("%d ", c[i]);
        }
    }
    
    int main() {
    #ifdef LOCAL
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code

    正解:

    首先注意到,选出n / 2 + 1个数,2倍的和大于总和,等价于选出n / 2 + 1个数,总和大于剩下的数。

    因为可以取n / 2 + 1个,那么先对A排序,B不动,先把A[1]选了(这个是用在证明A数组成立用的),A【1】是当前A中最大的了。当然了也选了一个B,就是选了B[A[1].id],

    然后每两个做一pair,选一个比较大的B,也就是max(B[A[i].id], B[A[i + 1].id])

    这样,B数组是满足的,这很容易证明,因为没一对中,都选了一个较大的。然后加上第一个,总和肯定大于剩下 的。

    也就是

    max(b[1], b[2]) >= min(b[1], b[2])

    max(b[3], b[4]) >= min(b[3], b[4])

    max(b[5], b[6]) >= min(b[5], b[6])

    那么全部相加,不等号方向不变。而且开头还有一个b[A[1].id]加了进来,所以是严格大于的。

    再来看看A的证明。

    第一是选了a[1]

    然后选a[2]和a[3]的那个呢?不固定的,还要看B,但是不管,有以下不等式。

    a[1] >= any(a[2], a[3])

    any(a[2], a[3]) >= any(a[4], a[5])

    any(a[4], a[5]) >= any(a[5], a[6])

    也就是,你选了一个a[1],然后a[2]和a[3]选那个是没关系的,可以用a[1]和它比较,然后又因为选了any(a[2], a[3]),那么你a[4]和a[5]选那个是没所谓的,因为可以用any(a[2], a[3])和它比较。

    最后,any(a[n - 1], a[n]) > 0,所以是严格大于的。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 1e5 + 20;
    struct Node {
        int a, id;
        bool operator < (const struct Node & rhs) const {
            return a > rhs.a;
        }
    }a[maxn];
    int b[maxn];
    vector<int>ans;
    void work() {
        int n;
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i].a;
            a[i].id = i;
        }
        for (int i = 1; i <= n; ++i) {
            cin >> b[i];
        }
        sort(a + 1, a + 1 + n);
        int sel = n / 2 + 1;
        ans.push_back(a[1].id);
        for (int i = 2; i <= n; i += 2) {
            int want = a[i].id;
            if (i + 1 <= n && b[want] < b[a[i + 1].id]) {
                want = a[i + 1].id;
            }
            ans.push_back(want);
        }
        cout << ans.size() << endl;
        for (int i = 0; i < ans.size(); ++i) {
            cout << ans[i] << " ";
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
    IOS;
        work();
        return 0;
    }
    View Code

    2017-4-23 22:22:03

    要开始补sg函数(博弈)和构造题。先复习下字符串准备省赛。

  • 相关阅读:
    【译】深入理解G1的GC日志(一)
    【译】深入理解G1的GC日志(一)
    【译】深入理解G1的GC日志(一)
    Java 8 Time Api 使用指南-珍藏限量版
    颠覆微服务认知:深入思考微服务的七个主流观点
    函数式编程让你忘记设计模式
    使用Optional摆脱NPE的折磨
    使用Optional摆脱NPE的折磨
    使用Optional摆脱NPE的折磨
    面试官:优化代码中大量的if/else,你有什么方案?
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6750317.html
Copyright © 2011-2022 走看看