题意:结婚纪念日到了,给老婆买花。花有m种,每种无数个。你要买n朵。第i种花的第一朵给你老婆ai的愉悦值,第二朵开始则是bi的愉悦值。你想让老婆愉悦值最高,求最高的方案。
分析:哭了,这题我赛后看了三分钟就想到思路了。为什么赛中我不看题。其实这场比赛就a题比较不正常的卡我(其实是我zz了)
首先我们要明确一个事实,这也是题目最重要的隐藏信息:买多种花的话最多只会买一种。因为如果买了两种就意味着要么是相等(可以买一种),要么不相等,那肯定有更优的解。因此只可能买一种。
既然如此,策略就很清晰了。首先造一个结构体,元素是int happy;int ab;int i;int ans=-1;分别代表带来的幸福值,是a还是b(0代表a,1代表b),在原数组中的位置在哪里(方便定位另一个元素的位置),加上一个下文要用的值。
定义一个数组flag。初始值是0,如果显示1代表ai已经取过了。
然后将所有ai和bi全部处理成结构体模式。然后按照happy的大小从大到小排序。排序完成后依次处理。int tmp=0;如果是ai,tmp+=ai,ans=tmp;n--;直接往下,将ai对应的下标标记为1.如果是bi,如果对应的ai已经取过,ans=tmp+n*bi;否则ans=tmp+ai+(n-1)*bi。
最后直接找最大的ans即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll n,m;
ll a[N],b[N];
ll flag[N];
struct Shu
{
ll happy;
ll ab;
ll pos;
ll ans;
}shu[2*N];
bool cmp(Shu x,Shu y)
{
return x.happy>y.happy;
}
void rlmn()
{
scanf("%lld%lld",&n,&m);
for (int i=0;i<m;i++)
{
flag[i]=0;
}
for (int i=0;i<2*m;i++)
{
shu[i].happy=0;
shu[i].ab=-1;
shu[i].pos=0;
shu[i].ans=-1;
}
for (ll i=0;i<m;i++)
{
scanf("%lld%lld",&a[i],&b[i]);
shu[i*2].happy=a[i];
shu[i*2].ab=0;
shu[i*2].pos=i;
shu[i*2+1].happy=b[i];
shu[i*2+1].ab=1;
shu[i*2+1].pos=i;
}
sort(shu,shu+2*m,cmp);
ll tmp=0;
for (ll i=0;i<2*m;i++)
{
if (shu[i].ab==0)
{
flag[shu[i].pos]=1;
tmp+=shu[i].happy;
shu[i].ans=tmp;
n--;
}
else
{
if (flag[shu[i].pos])//之前已经买过
{
shu[i].ans=tmp+n*shu[i].happy;
}
else//没买过
{
shu[i].ans=tmp+a[shu[i].pos]+(n-1)*shu[i].happy;
}
}
if (n<=0) break;
}
ll res=-1;
for (ll i=0;i<2*m;i++)
{
if (shu[i].ans>res)
{
res=shu[i].ans;
}
}
printf("%lld\n",res);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)rlmn();
return 0;
}
wa点:
1.没有考虑n减着减着<=0了,就会造成买负花。
2.一开始没有考虑到每种花买一朵的特殊情况,只在bi处结算,没在ai处结算