C. Arthur and Table

链接

[https://codeforces.com/contest/557/problem/C]

题意

给你每个木棍的长度,以及移除每个木棍的代价
使得桌子稳定,最长的木棍必须大于剩下的一半

分析

这个数据范围,就是得暴力和前缀和还有一些技巧
枚举每一种长度,大于它的全部移除,
那么剩下的就尽可能地移除少量的木棍,而且移除可以移除的最小代价
复杂度2e7左右。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct str{
	int l,d;
}a[maxn];
int num[maxn];//长度为i的数量 
int prenum[maxn];//长度小于等于i的有多少个 
int s[maxn];// 第i个之前全部移除需要的代价 
int t[210];//当前代价为i的有多少个 
bool cmp(str x,str y){
	if(x.l==y.l) return x.d<y.d;
	return x.l<y.l;
}

int main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int n;
	while(cin>>n){
		memset(num,0,sizeof(num));
		memset(prenum,0,sizeof(prenum));
		memset(s,0,sizeof(s));
		memset(t,0,sizeof(t));
		for(int i=1;i<=n;i++)
		{
			cin>>a[i].l;
			num[a[i].l]++;
		}
		
		for(int i=1;i<=n;i++)
		cin>>a[i].d;
		
		sort(a+1,a+n+1,cmp);
		 
		 for(int i=1;i<=n;i++)
		 s[i]=s[i-1]+a[i].d;
		 
		 for(int i=1;i<=100000;i++)
		 prenum[i]=prenum[i-1]+num[i];
	     int ans=1e9;
		 
		 for(int i=1;i<=100000;i++)
		 {
		 	if(!num[i]) continue;
		 	int tem=prenum[i]-(2*num[i]-1);//该移除的个数 
		 	int cur=s[n]-s[prenum[i]];
		    //cout<<i<<' '<<tem<<' '<<cur<<endl;
		 		for(int j=1;j<=200&&tem>0;j++)
		 		{
		 			if(tem>=t[j]){
		 				tem-=t[j];
		 				cur+=t[j]*j;
					 }
					 else {
					 	cur+=tem*j;
					 	tem=0;
					 }
				 }
			 ans=min(ans,cur);
			 for(int j=prenum[i-1]+1;j<=prenum[i];j++)
			 t[a[j].d]++;
			
		 }
		 cout<<ans<<endl;
	}
	return 0;
}
posted @ 2019-06-05 22:14  ChunhaoMo  阅读(184)  评论(0编辑  收藏  举报