您的位置:首页 > 其它

51nod 1461

2016-11-05 14:12 197 查看
原题链接

将桌腿按长度排序,枚举终态的最长桌腿长度L,假设该长度的桌腿有M条,显然长度大于L的桌腿必须去掉,剩下长度小于L的保留花费最大的M-1条即可。

用大根堆保存长度小于L的桌腿。

#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<fstream>
#include <iostream>
#include<algorithm>
#define debug puts("ssssssssssss")
#define ll long long
#define MP make_pair
#define mm(a,b) memset(a,b,sizeof(a))
#define rep(a,b) for(int a=1;a<=b;a++)
#define e 2.7182818284590452354
using namespace std;
const int MOD=100000007;
const int maxb=500+10;
const int MAXN=100005;
const int maxn=1005;
const double eps=1e-10;
int n, k;
struct node{
int li, di;
bool operator <(const node &a)const{
return li<a.li;
}
};
node dk[MAXN];
int li[MAXN];
ll sum[MAXN];
priority_queue<int,vector<int>,greater<int> > Q1, Q2;
int main(){
//    ifstream fin("in.txt");
//    ofstream fout("out.txt");
int n;

scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&dk[i].li);
for(int i=1;i<=n;i++) scanf("%d",&dk[i].di);
sort(dk+1,dk+1+n);
dk[0].li=-1;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+dk[i].di;
}
ll ans=sum
, sum1=0;
for(int l=1;l<=n;l++){
if(dk[l].li!=dk[l-1].li){
int r=l;
while(r+1<=n&&dk[r+1].li==dk[l].li) r++;
ll temp=sum
-sum[r];
int len=r-l+1;
if(len>=2){
int lim=min(l-1,len-1);
while(!Q1.empty()&&!Q2.empty()&&Q1.top()<-Q2.top()){
int reg=Q1.top();
sum1-=Q1.top();
Q1.pop();
Q1.push(-Q2.top());
sum1-=Q2.top();
Q2.pop();
Q2.push(-reg);
}
while(Q1.size()<lim&&!Q2.empty()){
sum1-=Q2.top();
Q1.push(-Q2.top());
Q2.pop();
}
while(Q1.size()>lim){
sum1-=Q1.top();
Q2.push(-Q1.top());
Q1.pop();
}
temp+=sum[l-1]-sum1;
}else{
temp+=sum[l-1];
}
/*            if(ans>temp){
printf("l=%d r=%d\n",l, r);
printf("sum1=%lld\n",sum1);
}*/
ans=min(ans,temp);
}
Q1.push(dk[l].di);
sum1+=dk[l].di;
}
printf("%lld\n",ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: