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.

 
 
#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;
}
贪心
 

猜你喜欢

转载自www.cnblogs.com/albert-biu/p/10802812.html
今日推荐