题目
大致翻译:
弗拉基米尔想为他的妻子准备一份礼物:他们有一个周年纪念日!他决定给她买花。
弗拉基米尔去了一家花店,他惊奇地发现那里有m种花卉出售,而且每种花卉都有无限量的供应。弗拉基米尔想选择鲜花来最大化妻子的幸福。他知道,在收到第i种类型的第一朵花后,他的妻子的幸福感增加了ai,在收到每一朵连续的这种类型的花后,她的幸福感增加了bi。也就是说,如果在所选的花中有席席I型0朵,他的妻子得到Ai+(Xi×1)Bi的额外幸福(如果没有I型花,她就不会得到这种类型的花)。
请帮助弗拉基米尔选择n朵鲜花,以最大限度地实现他妻子的全部幸福。
输入
第一行包含唯一的整数t(1≤t≤10000),即测试用例数。接下来是测试用例的t描述。
每个测试用例描述从两个整数n和m(1≤n≤109,1≤m≤100000)开始,Vladimir需要选择的花的数量和可用花的类型的数量。
以下m行描述了花的类型:每行包含第i种可用花的整数ai和bi(0≤ai,bi≤109)。
测试用例用一个空行隔开。保证所有测试用例中m值之和不超过100000。
输出
对于每一个测试用例,输出一个整数:弗拉基米尔的妻子在选择n朵鲜花后的最大幸福感。
注意
在第一个例子中,弗拉基米尔可以挑选第一种类型的一朵花和第二种类型的三朵花,在这种情况下,总幸福等于5+(1+2⋅4)=14。
在第二个例子中,弗拉基米尔可以挑选第一种类型的两朵花,第二种类型的两朵花,第三种类型的一朵花,在这种情况下,总幸福等于(5+1⋅2)+(4+1⋅2)+3=16。
思路:枚举bi,先按ai排序,运用upper_bound进行二分查找刚大于bi的a的范围,先将大于bi的a全部买一次再买bi,然后寻找最大的情况;注意一些边界条件,在代码中有注释;
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define eps 1e-6
typedef long long ll;
struct flo{
ll a,b;
}f[100010];
ll sum[100010];
ll c[100010];
int n,m;
bool cmp(flo a,flo b){
return a.a <b.a ;
}
ll find(int x){
ll pos=upper_bound(c+1,c+1+m,f[x].b)-c;
if(m-pos+1>=n) return sum[m-n+1];//如果大于f[x].b的a的数量的大于买的花的数量 则不会出现同种花买第二次的情况
ll rest=n-(m-pos+1)-1;//需要买同种花的数量-1 因为后面还需判断此花是否买过
if(pos<=x){//如果该花已经买过一次,则之后买则为b的值
rest++;
return rest*f[x].b+sum[pos];
}
return rest*f[x].b+sum[pos]+f[x].a ;//若该花还未买过,则需要先买一次
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d",&f[i].a ,&f[i].b ),c[i]=f[i].a ;
sort(f+1,f+m+1,cmp);
sort(c+1,c+m+1);
sum[m+1]=0;
for(int i=m;i>0;i--)
sum[i]=sum[i+1]+c[i];
ll ans=0;
for(int i=1;i<=m;i++){
ans=max(ans,find(i));
}
printf("%lld\n",ans);
}
return 0;
}