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 CCPC2018 桂林 A: Array Merge(贪心、带权并查集合并) 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.

    CCPC2018 桂林 A: Array Merge(贪心、带权并查集合并)
#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\n", ++cnt, ans);
    }
    return 0;
}
贪心

 

 
上一篇:opensuse免安装mysql


下一篇:简单的排列问题的总结