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\n", ++cnt, ans);
    }
    return 0;
}

贪心

原文地址:https://www.cnblogs.com/albert-biu/p/10802812.html

时间: 2024-10-08 16:41:52

CCPC2018 桂林 A: Array Merge(贪心、带权并查集合并)的相关文章

poj1417 带权并查集+0/1背包

题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是魔. 对于这些问题,我们只需要发现,如果回答对方是魔,那么即可以判断出这两个不是同一种族,而如果回答对方是神,那么说明这两个是同一种族,那么就可以用带权并查集合并这些神和魔,然后记录两种分别多少个,这样当所有询问都处理完时我们就可以得到一系列的集合,每个集合分别有它的两个种族的人数,但是此时对于每个

HDU 5176 The Experience of Love (带权并查集 + 贪心)

The Experience of Love Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 275    Accepted Submission(s): 111 Problem Description A girl named Gorwin and a boy named Vivin is a couple. They arrived

HDU 3047 Zjnu Stadium 带权并查集

题目来源:HDU 3047 Zjnu Stadium 题意:给你一些人 然后每次输入a b c 表示b在距离a的右边c处 求有多少个矛盾的情况 思路:用sum[a] 代表a点距离根的距离 每次合并时如果根一样 判断sum数组是否符合情况 根不一样 合并两棵树 这里就是带权并查集的精髓 sum[y] = sum[a]-sum[b]+x 这里y的没有合并前b的根 #include <cstdio> #include <cstring> using namespace std; cons

并查集2——带权并查集

路径压缩 前面的并查集的复杂度实际上有些极端情况会很慢.比如树的结构正好是一条链,那么最坏情况下,每次查询的复杂度达到了 O(n). 路径压缩 的思想是,我们只关心每个结点的父结点,而并不太关心树的真正的结构. 这样我们在一次查询的时候,可以把查询路径上的所有结点的 father[i] 都赋值成为根结点.只需要在我们之前的查询函数上面很小的改动. int get(int x) { if (father[x] == x) { // x 结点就是根结点 return x; } return fath

POJ 1182 食物链 [并查集 带权并查集 开拓思路]

传送门 P - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1182 Appoint description:  System Crawler  (2015-01-27) Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物

【HDOJ3047】Zjnu Stadium(带权并查集)

题意:浙江省第十二届大学生运动会在浙江师范大学举行,为此在浙师大建造了一座能容纳近万人的新体育场. 观众席每一行构成一个圆形,每个圆形由300个座位组成,对300个座位按照顺时针编号1到300,且可以认为有无数多行.现在比赛的组织者希望观众进入场地的顺序可以更加的有趣,在门票上并没有规定每个人的座位,而是与这个圈中某个人的相对位置,可以坐在任意一行. 门票上标示的形式如下:A B x 表示第B个人必须在A的顺时针方向x个位置(比如A坐在4号位子,x=2,则B必须坐在6号位子). 现在你就座位志愿

poj1182食物链,经典带权并查集

动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之一时,这句话就是假话,否

【BZOJ-4690】Never Wait For Weights 带权并查集

4690: Never Wait for Weights Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 88  Solved: 41[Submit][Status][Discuss] Description 在实验室中,Nathan Wada作为助手的职责是测定两个样品的重量差异.当样品的差异很小时,使用天平能比使用弹簧秤得到更精确的结果,所以他只使用天平来测得一些样品的重量差.他偶尔会被询问一些样品的重量差,而他能否回答这些问题取决于在回答相应

HDU_3172_带权并查集

Virtual Friends Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8229    Accepted Submission(s): 2363 Problem Description These days, you can do all sorts of things online. For example, you can u