SCUT校赛131:小P玩游戏II(贪心 & 思维)

来源:互联网 发布:python 数组减法 编辑:程序博客网 时间:2024/04/26 22:22

题目描述

PP最近迷上了一个游戏,但他在玩游戏的时候遇到了一个问题。

PP控制nn 个角色,标号为11nn,小PPKK个怪物可以分配给这nn个角色击杀,一个怪物只能分配给一个角色,并且必须要分配给一个角色。

对于第 i\,(1 \leq i \leq n)i(1in)个角色,如果没有分配到一个怪物,那么它就会获得经验c_ici,如果分配到了t\,(t \geq 1)t(t1)个怪物,那么它会获得经验a_i + t b_iai+tbi

PP要把KK个怪物分配给这nn个角色,问所有角色获得的经验总和最多是多少。


输入格式

输入第一行一个整数TT,表示有TT组数据。

对于每组数据,第一行两个正整数nnKK

接下来nn行,每行三个整数a_i,b_i,c_iai,bi,ci

1 \leq T \leq 501T50

1 \leq n, K \leq 1000001n,K100000

1 \leq a_i, b_i, c_i \leq 1000001ai,bi,ci100000


输出格式

对于每组数据,输出一个整数表示答案。


样例数据

输入

22 24 1 11 3 32 24 1 11 3 4

输出

910

备注


思路:(参考题解和师兄的代码)最佳分配的情况是这样的,分配到>1只怪的人一定<=1个,而这个人又是已分配到怪里面的人b值最大的,其余未分配到怪的人ai+bi-ci <= b,那么这个人是谁无法确定,所以枚举一下这个人就行。

# include <bits/stdc++.h># define ll long longusing namespace std;const int maxn = 1e5;struct node{    int a, b, c, d;}m[maxn+3];bool cmp(node x, node y){    return x.d > y.d;}ll sum[maxn+3];int main(){    int t, n, k;    scanf("%d",&t);    while(t--)    {        ll tot = 0;        scanf("%d%d",&n,&k);        for(int i=1; i<=n; ++i)        {            scanf("%d%d%d",&m[i].a, &m[i].b, &m[i].c);            m[i].d = m[i].a + m[i].b - m[i].c;        }        sort(m+1, m+1+n, cmp);        for(int i=1; i<=n; ++i)            tot += m[i].c, sum[i] = sum[i-1] + m[i].d;        ll ans = 0;        for(int i=1; i<=n; ++i)        {            int l = 1, r = min(n,k-1);//k-1为上限是因为有一个怪已经分配给i了。            while(l<=r)            {                int mid = l+r>>1;                if(m[mid].d > m[i].b)                    l = mid+1;                else                    r = mid-1;            }            if(r < i) ans = max(ans, (ll)tot + sum[r] + m[i].d + (ll)(k-r-1)*m[i].b);            else ans = max(ans, (ll)tot + sum[r] + (ll)(k-r)*m[i].b);//这里比较巧妙,当r==k-1时这样处理貌似有bug,因为最佳可能是每个人分一个怪,但这里剩下的一个怪强制分给i了,然而枚举到最后一个人时又正确了。        }        printf("%lld\n",ans);    }    return 0;}



0 0
原创粉丝点击