我智商太低,考试没磨出来。。。
看到200想到桶排,然后先按长度排序,一个一个添加,用一些前缀和数组,就可以直接求出比当前枚举的长度大的总消耗能量值,然后预处理当前长度有多少个,然后再到比这个长度小得里面去找。注意长度相同时要跳过,只枚举一次,不然可能删除之前一个相同长度的桌脚,然而网上很多题解代码没这个处理也过了,cf竟然数据弱,没人hack吗? =_=
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 100010
using namespace std;
int n,ans=2000000001;
struct leg{int l,d;}a[maxl];
int num[maxl],sum[maxl];
int in[210];
bool cmp(const leg &x,const leg &y)
{
return x.l<y.l;
}
void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i].l),num[a[i].l]++;
for(int i=1;i<=n;i++)
scanf("%d",&a[i].d),sum[a[i].l]+=a[i].d;
sort(a+1,a+1+n,cmp);
for(int i=1;i<maxl;i++)
sum[i]+=sum[i-1];
}
void mainwork()
{
int cst,res;
for(int i=1;i<=n;i++)
{
if(a[i].l==a[i-1].l)
{
while(a[i].l==a[i-1].l)
{
in[a[i].d]++;
i++;
}
i--;continue;
}
cst=sum[maxl-1]-sum[a[i].l];
res=num[a[i].l]-1;
for(int j=200;j>=1;j--)
if(in[j])
if(res-in[j]>=0)
res-=in[j];
else
{
cst+=j*(in[j]-res);
res=0;
}
ans=min(ans,cst);
in[a[i].d]++;
}
}
void print()
{
printf("%d",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}