hdu个人赛6—1009

小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个角色,问所有角色获得的经验总和最多是多少。
 

Input
输入第一行一个整数T,表示有T组数据。
对于每组数据,第一行两个正整数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; 
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值