Codeforces Round #311 (Div. 2) C. 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.
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.
Print a single integer — the minimum number of energy units that Arthur needs to spend in order to make the table stable.
2
1 5
3 2
2
3
2 4 4
1 1 1
0
6
2 2 1 1 3 3
4 3 5 5 2 1
8
题意:
一张桌子有n条长度不全相同的腿,拆掉每个桌腿有一定代价。
长度为最大值的桌腿数量必须超过此时桌腿总量的一半,桌子才算平稳。
问要想使桌子平衡最少需要付出多少代价。
分析:
枚举稳定时桌腿长度的最大值L,那么超过L的桌腿一定要拆掉。
如果拆掉了比L长的桌腿仍不满足L长度的桌腿超过总桌腿的一半,则从比L小的桌腿中拆除代价小的桌腿。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #define eps 10e-13 using namespace std; typedef long long ll; struct node { int l,d; }leg[100010]; int num[100010]; //num[i]:长度为i的桌腿数量 int c[100010]; //c[i]:排序后前i+1条桌腿的拆除总代价 int n[100010]; // n[i]:长度小于等于i的桌腿的总数量 int D[205]; // D[i]:拆除代价为i的桌腿数量 bool cmp(node x,node y) //按桌腿长度从小到大,长度相等时拆除代价从小到大排序 { if(x.l == y.l) return x.d<y.d; return x.l<y.l; } int main() { int N; while(~scanf("%d",&N)) { memset(c,0,sizeof(c)); memset(num,0,sizeof(num)); memset(n,0,sizeof(n)); memset(D,0,sizeof(D)); for(int i=0;i<N;i++) { scanf("%d",&leg[i].l); num[leg[i].l]++; } for(int i=0;i<N;i++) scanf("%d",&leg[i].d); sort(leg,leg+N,cmp); c[0] = leg[0].d; for(int i=1;i<N;i++) c[i] = c[i-1]+leg[i].d; n[0] = 0; for(int i=1;i<=100000;i++) n[i] = n[i-1]+num[i]; int res = 0x3f3f3f3f; for(int i=1;i<=100000;i++) //枚举最长桌腿长度 { if(!num[i]) continue; int tmp = n[i]-(2*num[i]-1); //最长桌腿长度为i时,长度为i的桌腿数量是否大于总量一半 int cur = c[N-1]-c[n[i]-1]; //cur=拆除长度>i的桌腿所花代价 while(tmp>0) //如果数量不过半,则从长度小于i的桌腿中选择代价小的拆除 { for(int j=1;j<=200;j++) { if(D[j]<=tmp) //代价为j的数量D[j] { cur += D[j]*j; tmp -= D[j]; } else { cur += tmp*j; tmp = 0; } } } res = min(res,cur); //更新答案 for(int j=n[i-1];j<n[i];j++) //按长度为i的桌腿的代价更新D,以便继续往后递推时 D[leg[j].d]++; //D[j]仍然记录的是桌腿长度小于所枚举值的代价为j的桌腿数量 } printf("%d\n",res); } return 0; }