zoukankan      html  css  js  c++  java
  • CCPC2018 桂林 A: Array Merge(贪心、带权并查集合并)

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 37  解决: 3
    [提交] [状态] [命题人:admin]

    题目描述

    Given two arrays A, B of length n and m separately, you have to merge them into only one array C (of length n + m) obeying the rule that the relative order of numbers in the same original array does not change in the new array.
    After merging, please calculate the  and output it.
    If there are multiple costs, please output the minimum of them.

    输入

    The first line of input file contains an integer T (1≤T≤50), describing the number of test cases.
    Then there are 3 T lines, with every three lines representing a test case.
    The first line of the test case contains two integers n and m (1≤n,m≤105) as described above.
    The second line of that contains n integers, ith of which represents the A[i].
    The third line of that contains m integers, ith of which represents the B[i].
    The numbers in both array have range in [0,108].
    It is guaranteed that the sum of n + m in all cases does not exceed 106.

    输出

    You should output exactly T lines. For each case, print Case d: (d represents the order of test case)first and then print a number representing the minimum cost on the same line.

    样例输入

    2
    2 2
    5 3
    4 5
    3 3
    1 3 5
    2 6 4
    

    样例输出

    Case 1: 40
    Case 2: 75
    

    提示

    Sample 1: Considering merging (5) (3) and [4] [5], we have following valid methods:
    - (5) (3) [4] [5], 1 5 + 2 3 + 3 4 + 4 5 = 43
    - (5) [4] (3) [5], 1 5 + 2 4 + 3 3 + 4 5 = 43
    - (5) [4] [5] (3), 1 5 + 2 4 + 3 5 + 4 3 = 40
    - [4] (5) (3) [5], 1 4 + 2 5 + 3 3 + 4 5 = 43
    - [4] (5) [5] (3), 1 4 + 2 5 + 3 5 + 4 3 = 41
    - [4] [5] (5) (3), 1 4 + 2 5 + 3 5 + 4 3 = 41
    So the answer is the minimum of the numbers above, 40.

     
    显然在没有顺序限制时,按从大到小的顺序组成新数组是最优的。在加入保持相对顺序不变的条件后,对于A、B中的最大值,在将它前面那个数加入新数组C后,应当立即把这个最大值加入C,那么就可以把最大值和其前面的数看作一个整体。
    类似的,可以把A和B两个数组分块,对于分块后的集合,易证优先放平均数较大的集合更优
     
     
    #include "bits/stdc++.h"
    
    using namespace std;
    const int maxn = 1e5 + 100;
    
    struct node {
        double sum;
        int cnt;
    
        friend bool operator<(node a, node b) {
            return a.sum * b.cnt < a.cnt * b.sum;
        }
    
        friend node operator+(node a, node b) {
            return (node) {a.sum + b.sum, a.cnt + b.cnt};
        }
    };
    
    int a[maxn], b[maxn];
    node S[maxn], T[maxn];
    vector<int> c;
    
    void add(int op, int from, int to) {
        for (int i = from; i <= to; i++) {
            if (op == 1) {
                c.push_back(a[i]);
            } else {
                c.push_back(b[i]);
            }
        }
    }
    
    
    int main() {
        freopen("in.txt", "r", stdin);
        int _, cnt = 0;
        scanf("%d", &_);
        int n, m;
        while (_--) {
            c.clear();
            scanf("%d %d", &n, &m);
            for (int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
            }
            for (int i = 1; i <= m; i++) {
                scanf("%d", &b[i]);
            }
            int tot1 = 0, tot2 = 0;
            for (int i = 1; i <= n; i++) {
                S[++tot1] = (node) {1.0 * a[i], 1};
                while (tot1 > 1 && S[tot1 - 1] < S[tot1]) {
                    S[tot1 - 1] = S[tot1 - 1] + S[tot1];
                    tot1--;
                }
            }
            S[++tot1] = (node) {-1.0, 1};
            for (int i = 1; i <= m; i++) {
                T[++tot2] = (node) {1.0 * b[i], 1};
                while (tot2 > 1 && T[tot2 - 1] < T[tot2]) {
                    T[tot2 - 1] = T[tot2 - 1] + T[tot2];
                    tot2--;
                }
            }
            T[++tot2] = (node) {-1.0, 1};
            int nows = 1, nowt = 1, fa = 1, fb = 1;
            while (nows < tot1 || nowt < tot2) {
                if (S[nows] < T[nowt]) {
                    add(2, fb, fb + T[nowt].cnt - 1);
                    fb = fb + T[nowt].cnt;
    
                    nowt++;
                } else {
                    add(1, fa, fa + S[nows].cnt - 1);
                    fa = fa + S[nows].cnt;
    
                    nows++;
                }
            }
            long long ans = 0;
            for (int i = 0; i < c.size(); i++) {
                ans = ans + (i + 1ll) * c[i];
            }
            printf("Case %d: %lld
    ", ++cnt, ans);
        }
        return 0;
    }
    贪心
     
  • 相关阅读:
    Java实现蓝桥杯七对数字
    Java实现蓝桥杯七对数字
    ubuntu下交叉编译windows c程序
    Linux下开发Windows平台运行的程序
    Fedora 11中用MinGW编译Windows的Qt4程序(在Linux系统下编译Windows的程序)
    C++内存问题大集合(指针问题,以及字符串拷贝问题,确实挺危险的)
    C/C++的编译器|编译环境(非常全面的比较)
    关于 js 中的 call 和 apply使用理解
    看我如何应对业务需求变化,领域模型调整?
    MVC 用扩展方法执行自定义视图,替代 UIHint
  • 原文地址:https://www.cnblogs.com/albert-biu/p/10802812.html
Copyright © 2011-2022 走看看