題目鏈接:http://codeforces.com/problemset/problem/557/C
題意:給你個n個腳的桌子(1 <= n <= 10^5),每個腳的長度是li(1 <= li <= 10^5),砍掉這個叫的費用是di(1 <= di <= 200)。一個桌子能穩定僅當桌子的最大長度的腳的個數超過所有腳的個數的一半。問你砍掉一些腳,使這些費用最少,使桌子穩定。
思路:一看到看到di只有200感覺就可以暴力記錄着來做。將li相同的放進同一個vector,然後記錄一個sum[i],表示從長度爲0的到長度爲i的所有桌腳的長度和。然後枚舉桌腳長度i,枚舉到這個長度i,說明大於i的桌腳都要砍掉,那麼當前耗費加上sum[maxn] - sum[i],然後耗費再加上在長度小於i的桌腳中需要砍掉的耗費最少的幾個桌腳,最後更新答案就好了。ps:題目中說什麼桌腳一個就必定穩定,桌腳兩個時要兩個等長才穩定,根本沒考慮就A了。。。
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
using namespace std;
const int maxn = 100005;
int n;
struct ppp
{
int l,d;
}table[maxn];
vector<int> vec[maxn];
ll sum[maxn];
int cnt[205];
ll ans;
int main()
{
while(~scanf("%d",&n))
{
mem(cnt,0);
ans = 99999999999999LL;
int maxx = -1;
for(int i = 0;i < maxn;i++)vec[i].clear();
for(int i = 0;i < n;i++)scanf("%d",&table[i].l),maxx = max(maxx,table[i].l);
for(int i = 0;i < n;i++)scanf("%d",&table[i].d),vec[table[i].l].push_back(table[i].d);
ll temp;
sum[0] = 0;
for(int i = 1;i < maxn;i++)
{
temp = 0;
for(int j = 0;j < vec[i].size();j++)
{
temp += vec[i][j];
}
sum[i] = temp + sum[i - 1];
}
int count = 0;
for(int i = 0;i <= maxx;i++)
{
if(vec[i].size())
{
temp = sum[maxx] - sum[i];
int remain = count - vec[i].size() + 1;
if(remain > 0)
{
for(int j = 1;j <= 200 && remain > 0;j++)
{
if(remain >= cnt[j])
{
temp += j * cnt[j];
remain -= cnt[j];
}
else
{
temp += remain * j;
break;
}
}
}
count += vec[i].size();
for(int j = 0;j < vec[i].size();j++)
cnt[vec[i][j]]++;
ans = min(ans,temp);
}
}
printf("%I64d\n",ans);
}
}