题目大意:
有一张桌子,有n个腿。第i根腿的长度是li。
现在要拿掉一些腿,使得桌子稳定,拿掉第i根腿需要di的能量。
稳定的条件是,假如拿掉若干条腿之后,桌子还有k个腿,那么长度最长的腿的数目要超过一半。比如桌子有5根腿,那么至少要有三根腿是最长的。另外,只有一根腿的桌子是稳定的,两个腿的桌子想要稳定,必需长度是一样的。
你的任务是拿掉若干腿,使得桌子稳定,并且所消耗的能量要最少。
思路:按长度排序,枚举每个长度,比枚举长度长的全拆掉,前面的拆掉 枚举长度数量-1
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 100005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 100000000
int n;
int all = 0;
int cnt[205];
struct node
{
int l , val;
}a[maxn] , tmp[maxn];
bool cmp(node n1 , node n2)
{
if(n1.l == n2.l) return n1.val < n2.val;
return n1.l < n2.l;
}
bool cmp2(node n1 , node n2)
{
return n1.val < n2.val;
}
void solve()
{
int ans = INF;
int i = 0 , cost = 0 , num = 0 , j;
while(i < n)
{
cost = a[i].val;
// cnt[a[i].val]++;
num = 1;
for(j = i + 1; j < n ; j ++)
{
if(a[j].l == a[j-1].l) num++,cost+= a[j].val ;
else break;
}
all-=cost;
cost = all;
/* memcpy(tmp , a , (j-num)*8);
sort(tmp , tmp+j-num , cmp2);
int up = j + 1 - num - num;
for(int k = 0 ; k < up;k ++) cost += tmp[k].val;*/
int tmp = num;
num = j + 1 - num - num;
//num++;
for(int k = 1 ; k <= 200 ; k ++)
{
if(cnt[k])
{
// cout << k << endl;
if(cnt[k] < num) cost += k * cnt[k] , num -= cnt[k];
else {cost += k * num;break;}
}
}
ans = min(ans , cost);
// cout << ans << " test" << endl;
for(int k = i ; k < j ; k++)
{
cnt[a[k].val]++;
}
i = j;
}
printf("%d\n" , ans);
}
int main()
{
while(scanf("%d" , &n) != EOF )
{
all = 0;
mem(cnt , 0);
for(int i = 0 ; i < n ;i ++)
scanf("%d" , &a[i].l);
for(int i = 0 ; i < n ; i ++)
scanf("%d" , &a[i].val) ,all += a[i].val;
sort(a , a + n , cmp);
solve();
}
return 0;
}