Codeforces Round #311 (Div. 2) C. Arthur and Table (枚举+贪心+思维)

C. Arthur and Table
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Sample test(s)
Input
2
1 5
3 2
Output
2
Input
3
2 4 4
1 1 1
Output
0
Input
6
2 2 1 1 3 3
4 3 5 5 2 1
Output
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;
}
View Code

 

转载于:https://www.cnblogs.com/hadis-yuki/p/4689442.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值