CodeForces 557C Arthur and Table STL的使用
题意:一个桌子有n条腿,每条腿有一定的长度l,和砍下的花费w,现在规定,桌子稳的条件是长度最长的腿(可多个)的数量大于长度小于它的桌子腿数量,且不存在比他还长的桌子腿,求让桌子腿稳定的最小的花费
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1);
const int mod=100000000;
int max(int a,int b)
{return a>b?a:b;};
int min(int a,int b)
{return a<b?a:b;};
const int maxl=100000;
struct node{
int l,w;
}ne[100005];
bool cmp(node a,node b)
{
return a.l<b.l;
}
vector<int> numw[205];
int n,num[maxl+5],total[maxl+5];
void solve()
{
int ans=inf;
for(int i=1;i<=maxl;i++)
if(num[i])
{
int temp=total[i+1],k=num[i]-num[i+1];
int cnt=num[1]-num[i]-(k-1);
if(cnt>0)
{
for(int j=1;j<=200;j++)
if(numw[j].size())
{
//printf(":2\n");
if(cnt<=0) break;
int p=lower_bound(numw[j].begin(),numw[j].end(),i)-numw[j].begin();//花费为j的桌子腿中长度>=i的个数
temp+=min(p,cnt)*j;
cnt-=p;
// printf(":3\n");
}
}
ans=min(ans,temp);
}
printf("%d\n",ans);
}
void init()
{
memset(total,0,sizeof(total));
memset(num,0,sizeof(num));
for(int i=0;i<=200;i++)
numw[i].clear();
}
void input()
{
init();
//printf("||5\n");
for(int i=1;i<=n;i++)
{
scanf("%d",&ne[i].l);
num[ne[i].l]++;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&ne[i].w);
numw[ne[i].w].push_back(ne[i].l);
}
//printf("|||6\n");
sort(ne+1,ne+n+1,cmp);
for(int i=1;i<=n;)
{
int p=i;
while(ne[p].l==ne[i].l&&i<=n)
{
total[ne[p].l]+=ne[i].w;
i++;
}
}
for(int i=maxl;i>=1;i--)
{
total[i]+=total[i+1];
num[i]+=num[i+1];
}//total数组统计砍下长度>=i的所有桌子腿的总花费
//num数组记录长度>=i的桌子腿的个数
for(int i=1;i<=200;i++)
if(numw[i].size())
sort(numw[i].begin(),numw[i].end());
}
int main()
{
while(~scanf("%d",&n))
{
input();
solve();
}
return 0;
}
核心思路:先暴力枚举最长的桌子腿腿长(1e5),然后再按花费(<=200)进行从小到大的贪心选取
,每次在花费为w上进行贪心时,找出小于当前枚举的长度的桌子腿个数,本题的实现是个大难题
错因分析:本来想用优先队列来维护权花费为w的长度序列的,实现本代码中vector的操作,但是优先队列
没有迭代器,不支持begin()这个操作,也就是priority_queue<node> a[100],a[1]就是代表一个优先队列,没有a[1].begin()这个操作,事实上优先队列只有pop(),top(),和insert(),这三个操作,其实就是个堆。
你说,我们都会幸福的,对吧?