LuoguP2123 皇后游戏

Description

皇后有 \(n\) 位大臣,每位大臣的左右手上面分别写上了一个正整数。恰逢国庆节来临,皇后决定为 \(n\) 位大臣颁发奖金,其中第 \(i\) 位大臣所获得的奖金数目为第 \(i-1\) 位大臣所获得奖金数目与前 \(i\) 位大臣左手上的数的和的较大值再加上第 \(i\) 位大臣右手上的数。

形式化地讲:我们设第 \(i\) 位大臣左手上的正整数为 \(a_i\),右手上的正整数为 \(b_i\),则第 \(i\) 位大臣获得的奖金数目为 \(c_i\) 可以表达为:

\[c_i=\begin{cases} a_1+b_1 & i=1 \\ max(c_{i-1},\sum_{j=1}^i a_j)+b_i & 2\leq i\leq n \end{cases}\]

当然,吝啬的皇后并不希望太多的奖金被发给大臣,所以她想请你来重新安排一下队伍的顺序,使得获得奖金最多的大臣,所获奖金数目尽可能的少。

注意:重新安排队伍并不意味着一定要打乱顺序,我们允许不改变任何一位大臣的位置。

Input

第一行包含一个正整数 \(T\) \((1\leq T\leq10)\),表示测试数据的组数。

接下来 \(T\) 个部分,每个部分的第一行包含一个正整数 \(n\) \((1\leq n\leq20000)\),表示大臣的数目。

每个部分接下来 \(n\) 行中,每行两个正整数,分别为 \(a_i\)\(b_i\) \((1\leq a_i,b_i\leq10^9)\),含义如上文所述。

Output

\(T\) 行,每行包含一个整数,表示获得奖金最多的大臣所获得的奖金数目。

Example

InputOutput
1
3
4 1
2 2
1 2
8
InputOutput
2
5
85 100
95 99
76 87
60 97
79 85
12

Solution

LuoguP1080 国王游戏 类似,采用贪心的策略。

考虑:若第 \(k\) 个大臣与第 \(k+1\) 个大臣交换位置后,两者间获得的较多奖金的一方的奖金减少。

设:排在第 \(k\) 个大臣前面的所有人的左手上的数的和为 \(s\) \((k=1,s=0)\),第 \(k-1\) 大臣的奖金为 \(c\) \((k=1,c=0)\)\(a_i\)\(b_i\) 依题设 ,

则有 \(max(max(c,s+a_{k+1})+b_{k+1},s+a_k+a_{k+1})+b_k<max(max(c,s+a_k)+b_k,s+a_k+a_{k+1})+b_{k+1}\)

我们先证明 \((1)\) \(max(x,z)<max(y,z)\) 作为交换 \(x\)\(y\) 的条件时与 \((2)\) \(x<y\) 等价:

\(x\geq y\),则不满足 \((1)\)\((2)\),不交换 \(x\)\(y\)
\(x<y\),则满足 \((2)\),交换 \(x\)\(y\),不满足 \((1)\)\((2)\)

综上,探究这类问题时,形如 \(max(x,z)<max(y,z)\) 的式子可化为 \(x<y\)

回到原题,

原式即 \(max(c-s,a_{k+1},a_k+a_{k+1}-b_{k+1})+s+b_k+b_{k+1}<max(c-s,a_k,a_k+a_{k+1}-b_k)+s+b_k+b_{k+1}\)

\(max(a_{k+1},a_k+a_{k+1}-b_{k+1})<max(a_k,a_k+a_{k+1}-b_k)\)

\(max(-a_k,-b_{k+1})<max(-a_{k+1},-b_k)\)

\((*)\) \(min(a_k,b_{k+1})>min(a_{k+1},b_k)\)

很遗憾,这并不是一个偏序关系,因为其不具有传递性。
举个栗子:\((3,5)\)\((1,1)\)\((1,7)\) 这个序列相邻的序偶均满足 \((*)\),而 \((1,1)\)\((1,7)\)\((3,5)\) 这样排序也满足 \((*)\),前者答案为 \(16\) ,后者答案为 \(14\) ,显然后者更优,我们如果单纯按照 \((*)\) 排序,无法保证结果的正确性。

实际上,我们可以在此之上进行一定的改良:

考虑 \((*)\) 不具有传递性的原因,当 \(min(a_k,b_{k+1})=min(a_{k+1},b_k)\) 时,不管我们交不交换,该条件均成立,这种不确定性会造成结果的不一致,这一点正是 \((*)\) 不具有传递性的原因。如在上面举出的栗子中,\((3,5)\)\((1,1)\) 交换与否就影响了最后的结果,可以看出 \(a_i\)\(b_i\) 的相对关系也会对最终的序列的顺序产生影响,我们不妨从如何消除这种影响开始考虑,既然 \(a_i\)\(b_i\) 的相对关系会影响排序,那么我们可以按相对关系将序偶分组,组内排好序后再按组排序。

设:\(d_i=sgn(a_i-b_i)\)

首先,我们按 \(d_i\) 将序偶分成三组,
在同一组内,序偶之间不存在 \(a_i\)\(b_i\) 的相对关系不一致的情况,易知在这种情况下 \((*)\) 具有传递性。具体来说就是:

对于 \(d_i=-1\) 的一组,若满足 \((*)\),则 \(a_k>a_{k+1}\),即按 \(a_i\) 升序排序即可
对于 \(d_i=0\) 的一组,则始终不满足 \((*)\),则无须排序
对于 \(d_i=1\) 的一组,若满足 \((*)\),则 \(b_{k+1}>b_k\),即按 \(b_i\) 降序排序即可

接下来考虑按组排序,

显然 \(d_i=0\) 的一组可以和其他的一组任意排序,那么我们将这一组放在中间即可
\(d_k=1\)\(d_{k+1}=-1\),则必满足 \((*)\),则 \(d_i=-1\) 的一组应放在 \(d_k=1\) 的一组的前面

如此,我们便得到了最终的序列,再遍历所有大臣求最大的奖金即可。


Code

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef struct{
    int a,b,d;
}h_type;

const int n_size=20005;

int T,n;
ll c[n_size];
h_type h[n_size];

bool cmp(h_type &x,h_type &y);

int main(void){
    scanf("%d",&T);
    for(int i=1;i<=T;i++){
        scanf("%d",&n);
        for(int j=1;j<=n;j++){
            scanf("%d%d",&h[j].a,&h[j].b);
            if(h[j].a==h[j].b)  h[j].d=0;
            else if(h[j].a<h[j].b)  h[j].d=-1;
            else    h[j].d=1;
        }
        sort(h+1,h+n+1,cmp);
        ll sum=0;
        for(int j=1;j<=n;j++){
            sum+=h[j].a;
            c[j]=max(c[j-1],sum)+h[j].b;
        }
        printf("%lld\n",c[n]);
    }
    return 0;
}

bool cmp(h_type &x,h_type &y){
    if(x.d!=y.d)    return x.d<y.d;
    if(x.d==-1) return x.a<y.a;
    if(x.d==1)  return x.b>y.b;
    return false;
}

转载于:https://www.cnblogs.com/MakiseVon/p/10598644.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值