Problem
来源:互联网 发布:知乎机构号注册流程 编辑:程序博客网 时间:2024/06/05 08:02
Arthur and Table
Arthur has bought a beautiful big table into his new flat. When he came home, Arthur noticed that the new table is unstable.In total the table Arthur bought has n legs, the length of the i-th leg is li.Arthur decided to make the table stable and remove some legs. For each of them Arthur determined number di — the amount of energy that he spends to remove the i-th leg.A table with k legs is assumed to be stable if there are more than half legs of the maximum length. For example, to make a table with 5 legs stable, you need to make sure it has at least three (out of these five) legs of the maximum length. Also, a table with one leg is always stable and a table with two legs is stable if and only if they have the same lengths.Your task is to help Arthur and count the minimum number of energy units Arthur should spend on making the table stable.
Input
The first line of the input contains integer n (1 ≤ n ≤ 105) — the initial number of legs in the table Arthur bought.The second line of the input contains a sequence of n integers li (1 ≤ li ≤ 105), where li is equal to the length of the i-th leg of the table.The third line of the input contains a sequence of n integers di (1 ≤ di ≤ 200), where di is the number of energy units that Arthur spends on removing the i-th leg off the table.
Output
Print a single integer — the minimum number of energy units that Arthur needs to spend in order to make the table stable.
Examples
Input21 53 2Output2Input32 4 41 1 1Output0Input62 2 1 1 3 34 3 5 5 2 1Output8
这题在Codeforces上的标签有brute force
、data structures
、dp
以及greedy
。一开始做以为是单纯的区间dp,想破头也没想明白。后来看题解也看得十分懵,自行设计了“再次使用sort(),直接将代价较小的桌腿置于数组前部,从而贪心地锯断这些桌腿”的方案。自觉十分完美,同时判断次数较少,最后结果是超时。我非常懊恼,最终还是强行把桶排序枚举的贪心策略给看明白了,解决了这道题。
简单地说,这题就是要找到一种长度
假设我们规定最长桌腿长度
刚才假设的是一种定长
这一题的关键在于
考虑如下样例(Codeforces test 5):
首先可以看出,必须令
如何得出最小代价呢?
从
注:代码中的枚举过程显示,对
#include <algorithm>#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1e5+4, INF = 0x7fffffff;int ocur[maxn], allCost[maxn], sumOcur[maxn], sumCost[maxn], barrel[204];// ocur[]:每种长度的桌腿总数;// allCost[]:每种长度的桌腿的代价总和;// sumOcur[]:桌腿出现次数的前缀和;// sumCost[]:桌腿代价总和的前缀和;// barrel[]:对代价的桶排序。struct leg{ int len, cost; bool operator < (const leg &a)const{ return len < a.len; }} legs[maxn];int main(){#ifdef TESTfreopen("test.txt", "r", stdin);#endif // TEST int n; while(cin >> n){ memset(ocur, 0, sizeof(ocur)); memset(allCost, 0, sizeof(allCost)); memset(sumOcur, 0, sizeof(sumOcur)); memset(sumCost, 0, sizeof(sumCost)); memset(barrel, 0, sizeof(barrel)); for(int i = 1; i <= n; i++){ scanf("%d", &legs[i].len); ocur[legs[i].len]++;// 记录某种长度的桌腿总数。 } for(int i = 1; i <= n; i++){ scanf("%d", &legs[i].cost); allCost[legs[i].len]+=legs[i].cost;// 记录某种长度的桌腿的总代价。 } sort(legs+1, legs+1+n);// 按桌腿长度进行排序。 int maxLen = legs[n].len;// 记录桌腿最大长度,用于规定后续枚举的上界。 for(int i = 1; i <= maxLen; i++){// 构造前缀和。 sumOcur[i] = sumOcur[i-1] + ocur[i]; sumCost[i] = sumCost[i-1] + allCost[i]; } int result = INF; for(int i = 1; i <= n; i++){// 枚举最终的最长桌腿长度。 int tempRes = sumCost[maxLen] - sumCost[legs[i].len];// 去掉大于当前枚举值的桌腿所需的代价。 int anotherLeftPart = ocur[legs[i].len] - 1;// 需要格外留下的最大桌腿数量。 for(int k = 200; k >= 1; k--){// 枚举长度小于当前桌腿长度的代价。 if(barrel[k] > 0){ if(barrel[k] <= anotherLeftPart) anotherLeftPart -= barrel[k]; else{ tempRes+=k*(barrel[k] - anotherLeftPart); anotherLeftPart = 0; } } } result = min(result, tempRes); barrel[legs[i].cost]++;// 延迟添加当前桌腿的代价值,确保每次枚举代价时所检查的代价值都属于“长度小于等于当前桌腿”的桌腿的代价。 } cout << result << endl; } return 0;}
- problem
- Problem
- problem
- Problem
- Problem
- Problem
- Problem
- Problem
- Problem
- problem
- Problem
- Problem
- Problem
- Problem
- Problem
- Problem
- Problem
- Problem
- jackson 完美用法
- JAVA项目连接到JDBC
- 欢迎使用CSDN-markdown编辑器
- dataFilter
- RxJava
- Problem
- Java并发编程实战(学习笔记五 第六章 任务执行)
- Django 的 URL name
- 27函数编程练习
- 二进制原码、反码、补码
- Eclipse中Hibernate插件安装
- Python 生成类字母验证码图片
- java多线程练习1
- Activity的启动模式都有哪些以及各自的特点