"Algorithm contest Step-up Guide" 1.7 binary heap

145. Supermarket

Supermarkets have N items, and each item has a profit pi expiration time di, every day can only sell a commodity, expired goods (ie the day di <= 0) can no longer sell.
The case of seeking reasonable arrangements to sell daily commodities, can get the maximum benefit is.

Input format
input comprises a plurality of test cases.
Each test case, the input to start the integer N, N, enter took on pi and DI, representing profit and expiration time of the i-th item.
Terminate input when the input, the data can be freely interspersed between any number of trailing spaces or blank lines, input files to ensure data is correct.

Output Format
For each product, the maximum output of a return value for the group.
Each result row.

Data range
0≤N≤10000,
1≤pi, di≤10000

Sample input:
4502101202301

7 20 1 2 1 10 3 100 2 8 2
5 20 50 10

Sample output:
80
185

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

typedef pair<int, int> PII;

int main()
{
    int n;
    while(cin >> n)
    {
        vector<PII> products(n); 
        for(int i = 0; i < n; i ++) cin >> products[i].second >> products[i].first; //按时间排序 把时间放在第一个关键字里
        
        sort(products.begin(), products.end()); //排序
        
        priority_queue<int, vector<int>, greater<int>> heap; //小根堆
        for(auto p : products) //遍历所有产品
        {
            heap.push(p.second); //把利润加入
            if(heap.size() > p.first) heap.pop();
        }
        
        int res = 0;
        while(heap.size()) res += heap.top(), heap.pop();
        
        cout << res << endl;
    }
    return 0;
}

146. Sequence

Given the m sequences, each comprising a non-negative integer n.
Now we can select a number from each sequence to form a sequence of m integers.
Obviously, we can get the total number of such sequences nm, then we can calculate the sum of the numbers in each sequence and, and the values obtained nm.
Now you find these sequences and among the smallest n value.

Input format
The first line input an integer T, represents the number of test cases included in the input.
Next, the input T of test cases.
For each test, the first line of the input two integers m and n.
M took input sequence of integers in m rows integer sequence is not more than 10,000.

Output Format
For each test, are sequentially output increment between the smallest and the sequence of n, values separated by spaces.
Each output per line.

Data range
0 <m≤1000,
0 <n≤2000

Sample input:
. 1
2. 3
. 1. 3 2
2 2. 3

Output Sample:
334

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

typedef pair<int, int>PII; // 存两个数,一个最小值的下标,一个是sum
const int N = 2010;

int m, n; //m行n列
int a[N], b[N], c[N]; //a b 为要合并的序列 c为辅助序列

void merge()
{
    priority_queue<PII, vector<PII>, greater<PII>> heap; //小根堆
    for(int i = 0; i < n; i++) heap.push({a[0] + b[i], 0}); //b[i] 与a[0] 相加 下标为0
    
    for(int i = 0; i < n; i++)
    {
        auto t = heap.top();
        heap.pop();
        int s = t.first, p = t.second; //t为值 p为下标
        c[i] = s;
        heap.push({s - a[p] + a[p + 1], p + 1});
    }
    for(int i = 0; i < n; i++) a[i] = c[i];
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%d%d", &m, &n); //读入行列
        for(int i = 0; i < n; i++) scanf("%d", &a[i]); // 读入第一行
        
        sort(a, a + n);
        
        for(int i = 0; i < m - 1; i++) //合并当前序列和下一个序列 合并 m-1 次
        {
            for(int j = 0; j < n; j ++) scanf("%d", &b[j]);
            merge(); //合并a和b 然后把结果存进a
        }
        
        for(int i = 0; i < n; i++) printf("%d ", a[i]);
        puts("");
    }
    return 0;
}

148. Merge fruit

In an orchard, Dada has shot down all the fruit, and different types of fruit into different piles.
Dada decided to put all the fruit of the synthetic pile.
Each combined, fruit piles People can merge together, equal to the weight of the physical consumption of fruit and two stacks.
As can be seen, all the fruits were combined after n-1 times, on the left a pile.
People When combined total fruit consumption combined physical strength is equal to the sum of each consumed.
But also because these fruits make great efforts to move back home, so when the fruit Dada merger to save energy as much as possible.
Number and the number of each type of fruit Fruit wt assumed that each are 1, and it is known fruit, your task is to design the combined sequence program to make physical People spend a minimum, and outputs the minimum value of the physical cost .
For example, three kinds of fruit, followed by the number 1,2,9.
1,2 stack may be first combined, the number of the new stack 3, 3 taxing.
Subsequently, the new stack and the third stack combined original, and to give the new stack number is 12, 12 is taxing.
Therefore, a total of taxing People = 3 + 12 = 15.
15 can be shown that the minimum value of the physical cost.

Input format
input consists of two lines, the first line is an integer n, the number of types of fruit.
The second line contains n integers, separated by spaces, the integer i ai
is the i-th number of fruit.

Output format
output comprises a line, which contains a single integer, i.e. the value of the minimum physical cost.
The input data to ensure that this value is less than 231.

Data range
1≤n≤10000,
1≤ai≤20000

Sample input:
. 3
. 1 2. 9

Sample output:
15

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

int main()
{
    int n;
    cin >> n;
    priority_queue<int, vector<int>, greater<int>> heap; //小根堆
    
    for(int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        heap.push(x);
    }
    
    int res = 0;
    while(heap.size() > 1) //小根堆有两个元素 合并最小的两个数
    {
        int a = heap.top(); heap.pop();
        int b = heap.top(); heap.pop();
        res += a + b;
        heap.push(a + b);
    }
    cout << res << endl;
    return 0;
}

149. Homer

Chasing the shadow of the man, it is the shadow. - Homer
Dada recently fell in love with literature.
She likes a lazy afternoon, and makes a product a cup of cappuccino, quietly reading her love of "Homer."
But from the "Odyssey" and "Iliad" composed a masterpiece "Homer" is too long, Dada wanted by an encoding such a way that it becomes shorter.
A "Homer" in n different words, numbered from 1 to n. Wherein the total number of i-th word appears as wi.
People want to replace the word with the i-th binary strings k si, so that it satisfies the following requirements:
For any 1≤i, j≤n, i ≠ j, are: Si not sj prefix.
People now want to know how to choose si, in order to minimize the length of the new "Homer" after replacing obtained.
In ensuring minimum total length, the longest Dada wanted to know the shortest length si is how much?
K is referred to as a hexadecimal string string, if and only if each character is an integer from 0 to k-1 (including 0 and k-1) of.
Str1 string is called the prefix string Str2, if and only if: exists 1≤t≤m, such Str1 = Str2 [1..t].
Wherein, m is the length of the string Str2, Str2 [1..t] t character string representing pre Str2 composition.

Input format
of the input file contains the first line two positive integers n, k, are separated by a single space intermediate, showing a total of n words of k binary strings need to be replaced.
2 ~ n + 1 of the line: first line i + 1 contains a non-negative integer wi, represents the number of occurrences of the i-th word.

Output format
output file comprises 2 rows.
A first output line integer, the "Homer" shortest length after subsequent re-encoded.
The second output line an integer of 1, in order to ensure the case where the shortest overall length, the shortest length of the longest string si.

Data range
2≤n≤100000,
2≤k≤9

Sample input:
. 4 2
. 1
. 1
2
2

Output Sample:
12 is
2

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

typedef long long LL;
typedef pair<LL, int> PLI;

int main()
{
    int n, k;
    cin >> n >> k;
    
    priority_queue<PLI, vector<PLI>, greater<PLI>> heap; //小根堆
    for(int i = 0; i < n; i++)
    {
        LL x; //输入值 LL
        cin >> x;
        heap.push({x, 0}); //将x插入优先队列里面 下标最开始高度是0
    }
    
    while((n - 1) % (k - 1)) heap.push({0, 0}), n++; // (n-1)%(k-1) != 0 往里面添加0
    
    LL res = 0;
    while(heap.size() > 1)
    {
        LL s = 0;
        int depth = 0; //新节点深度
        for(int i = 0; i < k; i ++) //取出最小的k个
        {
            auto t = heap.top();
            s += t.first; //权值
            depth = max(depth, t.second);
            heap.pop();
        }
        res += s;
        heap.push({s, depth + 1}); //父节点 高1
    }
    cout << res << endl << heap.top().second << endl;
    return 0;
}

147. Data Backup

You are an IT company as large office buildings or office computer data to do a backup.
However, data backup is tedious work, so you want to design a system to allow different building mutual backup between each other, while you sit at home and enjoy the fun of computer games.
Known offices are located in the same street, you decided to give these buildings pairing (two a group).
Each of the building such that they can pass between these two buildings laying cable network can be backed up to each other.
However, the high cost of network cable.
Local telecommunications company can only provide you with the K cable network, which means that you can only to K of buildings (a total of 2K office) schedule backups.
Any of an office building belong to a unique set of pairs (in other words, 2K of a building must be different).
In addition, Telecom Company was required length of the network cable (Kilometers) charges.
Thus, you need to choose which K for office makes the total length of the cable as short as possible.
In other words, you need to choose the K of office, making the distance between each pair of office buildings and (total distance) as small as possible.
Here's an example, suppose you have five clients, which are office buildings in a street, as shown in FIG.
The five offices are located at the starting point from the high street 1km, 3km, 4km, 6km and 12km office.
Telecom companies only provide you with K = 2 cables.

1111.png

The best example is the first pairing scheme and a second office connected, is connected to the third and fourth building.
Thus K = 2 can require the use of cables.
Article 1 cable length is 3km-1km = 2km, the cable length of the bar 2 is 6km-4km = 2km.
This scheme requires the total length of 4km pair network cable, and satisfy the minimum distance requirements.

Input format
of the first line of the input integer n and k, where n represents the number of the building, k is the number of available network cable.
The next n lines contains only one integer s, each represents the distance at the start of the street to the premises.
These integers will in turn appear in the order from small to large.

Output format of
the output should be a positive integers, to give a 2K office connected to a distinct minimum total length k of the network cable required.

Data range
2≤n≤100000,
1≤k≤n / 2,
0≤s≤1000000000

Sample input:
. 5 2
. 1
. 3
. 4
. 6
12 is

Sample output:
4

#include <iostream>
#include <queue>
#include <vector>
#include <set>

using namespace std;

typedef long long LL;
typedef pair<LL, int> PLI;
const int N = 100010;

int n, k; // n 表示办公楼的数目,k 表示可利用的网络电缆的数目
int l[N], r[N]; //双向链表左指针 右指针 
LL d[N]; //d是差值

void delete_node(int p)
{
    r[l[p]] = r[p]; //左边的右指针 = 右边
    l[r[p]] = l[p]; //右边的左指针 = 左边
}

int main()
{
    cin >> n >> k;
    
    for(int i = 0; i < n; i ++) cin >> d[i];
    for(int i = n - 1; ~i; i --) d[i] -= d[i - 1]; //当前与前一位的差值
    
    set<PLI> S; //需要动态修改 堆 用 set
    d[0] = d[n] = 1e15; //处理边界问题 定义两个哨兵
    for(int i = 0; i <= n; i ++)
    {
        l[i] = i - 1;
        r[i] = i + 1;
        if( i >= 1 && i < n) S.insert({d[i], i}); // push 值和下标
    }
    
    LL res = 0;
    while(k --)
    {
        auto it = S.begin(); //s里的最小值
        LL v = it->first; //值
        int p = it->second, left = l[p], right = r[p]; //下标 左儿子 右儿子
        
        S.erase(it);
        S.erase({d[left], left}), S.erase({d[right], right});//从平衡树删掉
        delete_node(left), delete_node(right); //删除左右两边的点
        res += v;
        
        d[p] = d[left] + d[right] - d[p];
        S.insert({d[p], p});
    }
    cout << res << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/wmxnlfd/p/10935393.html