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;
    }
    贪心
     
  • 相关阅读:
    多条件复合搜索的实现
    mysql字符集统一
    JS控制彈出窗口
    mysql常用sql
    正则表达式
    航班时间
    1月19日
    1月28日check小爱用
    在么小猫
    大连美发备考
  • 原文地址:https://www.cnblogs.com/albert-biu/p/10802812.html
Copyright © 2011-2022 走看看