小P玩游戏2
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 92 Accepted Submission(s): 13
Problem Description
小p最近迷上了一个游戏,但他在玩游戏的时候遇到了一个问题。
小P控制n个角色,标号为1到n,小P有K个怪物可以分配给这n个角色击杀,一个怪物只能分配给一个 角色,并且必须要分配给一个角色。
对于第i(1 <= i <= n)个角色,如果没有分配到一个怪物,那么它就会获得经验 ci ,如果分配到了t(t>=1)个怪物,那么它会获得经验 ai+tbi 。
小P要把K个怪物分配给这n个角色,问所有角色获得的经验总和最多是多少。
小P控制n个角色,标号为1到n,小P有K个怪物可以分配给这n个角色击杀,一个怪物只能分配给一个 角色,并且必须要分配给一个角色。
对于第i(1 <= i <= n)个角色,如果没有分配到一个怪物,那么它就会获得经验 ci ,如果分配到了t(t>=1)个怪物,那么它会获得经验 ai+tbi 。
小P要把K个怪物分配给这n个角色,问所有角色获得的经验总和最多是多少。
Input
输入第一行一个整数T,表示有T组数据。
对于每组数据,第一行两个正整数n和K。
接下来n行,每行三个整数 ai,bi,ci 。。
1 <= T <= 50
1 <= n,K <= 100000
1 <= ai,bi,ci <= 100000
对于每组数据,第一行两个正整数n和K。
接下来n行,每行三个整数 ai,bi,ci 。。
1 <= T <= 50
1 <= n,K <= 100000
1 <= ai,bi,ci <= 100000
Output
对于每组数据,输出一个整数表示答案。
Sample Input
2 2 2 4 1 1 1 3 3 2 2 4 1 1 1 3 4
Sample Output
9 10
【分析】
首先要发现一点...就是最多只有一个人可能被分到多个怪兽,因为如果某个人会分到两只怪兽,那么说明他的b收益要比所有分不到怪兽的人高,但是直接去找b最高的人肯定是有问题的,所以只要确定这个分到多只怪兽的人是谁就可以了,数据不大,枚举一遍就好了,相当于所有a+b-c小于当前第i个人的b值的人都不分怪兽,都给这个人。
也就是说在找到pos位置a[pos]+b[pos]-c[pos]<=b[i]时,左边c求和,右边a+b求和,当前人获得右边分完后的所有怪兽即可,
另外需要注意:
1.找到的pos位置有可能>i,那就要-c[i]+a[i]...
2.存在右边人数>怪兽数量的情况,所以考虑排序的时候从大到小排序,二分边界设置为min(k-1,n)因为第i个人需要分到怪兽,所以是k-1
//一开始正过来排,倒过来求前缀和,wa到爆炸....大概是我太菜了...不然思路是对的...代码写错了而已
【代码】
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <algorithm>
using namespace std;
struct xx{
long long a,b,c,dis;
}f[100010];
long long aa[100010];
long long bb[100010];
long long cc[100010];
long long dd[100010];
long long sum[100010];
long long summ[100010];
bool cmp(const xx&x,const xx&y)
{
return x.dis>y.dis;
}
int main()
{
int pp;scanf("%d",&pp);
while (pp--)
{
int n,m;scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&f[i].a,&f[i].b,&f[i].c);
f[i].dis=f[i].a+f[i].b-f[i].c;
}
sort(f+1,f+1+n,cmp);
sum[0]=summ[0]=0;
long long ans=-1;
for (int i=1;i<=n;i++) sum[i]=sum[i-1]+f[i].dis,summ[i]=summ[i-1]+f[i].c;
for (int i=1;i<=n;i++)
{
int l=1,r=min(m-1,n);
while (l<=r)
{
int mid=(l+r)>>1;
if (f[mid].dis>f[i].b) l=mid+1;
else r=mid-1;
}
if (r>=i)
ans=max(ans,(long long)sum[r]+(m-r)*f[i].b);
else ans=max(ans,(long long)sum[r]+f[i].dis+(m-r-1)*f[i].b);
}
printf("%lld\n",ans+summ[n]);
}
return 0;
}