[luogu]P2123 皇后游戏

题目传送门

分析

和国王游戏一样的思路直接考虑邻项交换
观察易知排在后面的大臣获得的奖赏一定更多
假设前 i1 位左手上的数和为a,第 i1 位获得奖赏为ci1;
对于排在第 i 位和第 i+1 位的大臣,
交换前,最大收益

w1=max(ci,j=1i+1aj)+bi+1==max(ci1+bi+bi+1,j=1iaj+bi+bi+1,j=1i+1aj+bi+1)

交换后,最大收益

w2=max(max(ci1,j=1i1aj+ai+1)+bi+1,j=1i+1aj)+bi==max(ci1+bi+bi+1,j=1i1aj+ai+1+bi+bi+1,j=1i+1aj+bi)

为了使交换前收益最小需要满足 w1<w2 ,则有

max(j=1iaj+bi+bi+1,j=1i+1aj+bi+1)<max(j=1i1aj+ai+1+bi+bi+1,j=1i+1aj+bi)max(ai+bi+bi+1,ai+ai+1+bi+1)<max(bi+bi+1+ai+1,ai+bi+ai+1)max(bi,ai+1)+ai+bi+1<max(bi+1,ai)+bi+ai+1max(ai+1,bi)<max(ai,bi+1)min(ai+1,bi)>min(ai,bi+1)min(ai,bi+1)<min(ai+1,bi)

所以只需要按这个规定贪心排序即可,个人认为传递性是存在的,手推了一下满足条件的所有情况,都没有矛盾(就是懒得用反证法)
但是没有考虑的是当 min(ai,bi+1)=min(ai+1,bi) 时应该如何排序
在一个相对的平衡里,如果我的某一方面属性在局面里有较大作用(比方说右手数字比你大,因为计算时最后直接加的右手数字)那么把我排在你前面才能使答案缩小,所以在这个平衡状态里我选择把右手数字大的排在前面。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define rg register
inline int read(){
    rg int x = 0, f = 1;
    rg char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}
const int N = 2e4 + 1;
struct minister{
    int l, r;
    bool operator <(minister b) const{
        if (min(l, b.r) == min(r, b.l))
            return l < b.l;
        return min(l, b.r) < min(r, b.l);
    }
    /*int l, r, d;
    bool operator < (minister b) const{
        if (d != b.d) return d < b.d;
        if (d < 0) return l < b.l;
        else return r > b.r;
    }*/
}a[N];
int n;
long long sum;
long long c[N];
inline void init(){
    n = read();
    for (int i(1); i <= n; ++i){
        a[i].l = read(), a[i].r = read();
    /*    if (a[i].l > a[i].r) a[i].d = 1;
        else if (a[i].l < a[i].r) a[i].d = -1;
        else a[i].d = 0;*/
    }
    sum = 0;
}
inline void doit(){
    sort(a + 1, a + 1 + n);
    for (int i(1); i <= n; ++i){
        sum += a[i].l;
        c[i] = max(c[i - 1], sum) + a[i].r;
    }
    printf("%lld\n", c[n]);
}
int main(){
    ios::sync_with_stdio(false);
    cout.tie(NULL);
    int T = read();
    while (T--){
        init();
        doit();
    }
    return 0;
}
posted @   ancer  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示