题目链接:http://http://codeforces.com/contest/557/problem/C
题意:一张桌子,最长的腿有一半以上就是稳定的,给出n条腿的长度以及卸掉那条退所需要的精力值,求最小需要多少精力使得桌子是稳定的。
解题思路:倒着来思考,先按照腿的长度从小到大排序,将长度相等的精力总和记录到数组sum[]里面去
举个例子,长度分别为1 1 2 2 3 3 3对应的精力是3 4 1 5 3 2 1 那么sum[ 1 ] = 7,sum[ 2 ] = 6,sum[ 3 ] = 6,总和s = 19;
假设一开始留下的是1,那么所需最小精力就是s-sum[ 1 ],然后将1所对应的精力值用数组C来记录,C[ 3 ]=1,C[ 4 ]=1,接着假设留下最大的是2,此时精力ans = sum[ 2 ],那么最多还可以留下1个比2小的数,暴力求出数组C中最大的精力值,即4,把4加到ans上去,此时所需最小精力就是s-ans,再把所有2对应的精力值记录到数组C中去……到后期,我们只要将ans加上最大的精力值即可,不用管加上的长度到底什么
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int num[100005];
int c[205],sum[100005];
struct node
{
int li,di;
}a[100005];
bool cmp(node b, node d)
{
if(b.li!=d.li) return b.li<d.li;
return b.di<d.di;
}
int main()
{
int n;
scanf("%d",&n);
memset(c,0,sizeof(c));
memset(sum,0,sizeof(sum));
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].li);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].di);
}
sort(a+1,a+n+1,cmp);
int l=1;
int s=0;
for(int i=1;i<=n;i++)
{
sum[l]+=a[i].di;
num[l]++;
s+=a[i].di;
if(a[i].li!=a[i+1].li) l++;
}
int cou = 0;
int minx=0x3f3f3f3f;
l=1;
int sum1=0;
int be=1,en;
int flag;
for(int i=1;i<=n;i++)
{
int ans=sum[l];
flag=0;
if(a[i].li!=a[i+1].li)
{
en=i;
flag=1;
cou+=num[l-1];
if(num[l]>cou)
{
sum1+=sum[l];
l++;
ans = sum1;
minx = min(minx,s-ans);
}
else
{
if(l!=1)
{
int ti=0,t=0;
for(int j=200;j>=1;j--)
{
if(c[j]==0) continue;
if(t+c[j]>=num[l])
{
ans+=j*(num[l]-1-t);
break;
}
else
{
t+=c[j];
ans+=j*c[j];
}
}
}
minx = min(minx,s-ans);
l++;
}
}
if(flag==1)
{
for(int j=be;j<=en;j++)
{
c[a[j].di]++;
}
be=en+1;
}
}
cout<<minx<<endl;
return 0;
}