Reinforced Problem

Reinforced Problem

题目描述

原神是一款开放世界的动作角色扮演游戏,玩家一次可以选择四名角色参与战斗,并且在战斗中可以快速切换。角色可以通过各种方式增强他们的力量,例如提高角色的等级,改进角色装备的圣遗物和武器。

zml 就是一名忠实的原神玩家,但是由于 ffg 对原神的强烈抵制,zml 不得不规划一下自己玩原神的时间。

zml 第 i 天玩原神都会有一个喜悦值 ai,与此同时,ffg 也会在这天有一个对原神玩家的愤怒值 bi,并且假如 zml 连续几天玩原神这个愤怒值会累加,假如有一天没有玩原神,ffg 就会原谅他,然后愤怒值清空,但是 zml 的喜悦值不会受到影响。

ffg 有个忍耐值 m,只要 ffg 的愤怒值没有超过 m,ffg 就不会爆发,zml 就可以安然无恙的玩原神,否则 ffg 就会把他炖了。

现在基于 zml 每天的喜悦值和 ffg 对原神玩家的愤怒值,请你输出 zml 的最大喜悦值(当然,zml 不想被炖)。

输入描述: 

第一行包含一个整数 T(1T104),表示测试用例的数量。

每个测试用例的第一行包含一个整数 n,m(1n105,0m1014)n 表示天数,m 表示 ffg 的最大愤怒值。

第二行包含 n 个数 a1,a2,,an(1|ai|109),表示 zml 在第 i 天的喜悦值 ai

第三行包含 n 个数 b1,b2,,bn(1|bi|109),表示 ffg 在第 i 天的愤怒值 bi

保证所有测试用例的 n 加起来的和不超过 2×105

输出描述:

对于每个测试用例,输出一个整数,表示 zml 玩原神的最大喜悦值(不被邪恶的 ffg 炖的前提下)。

示例1

输入

1
4 6
8 4 3 1
5 2 -2 2

输出

12

说明

对于样例 1,zml 会选择第 1 天,第 3 天和第 4

- 第 1 天 ffg 的愤怒值为 5, zml 的喜悦值为 8

- 第 2 天由于 zml 不选择玩原神,所以 ffg 的愤怒值降为 0,zml 的喜悦值仍然为 8

- 第 3 天 ffg 的愤怒值为 2,zml 的喜悦值为 11

- 第 4 天 ffg 的愤怒值为 1,zml 的喜悦值为 13

为什么 zml 不选择第 1 天,第 2 天和第 3 天呢?这连续 3 天的愤怒值之和是 5。 这是因为假如选择第 1 天,第 2 天和第 3 天,ffg 在第 2 天愤怒值为 7,ffg 就会把 zml 炖了,也就是说,假如 ffg 的愤怒值中途大于 m,即使后面降下来了也无济于事。

示例2

输入

5
6 9
2 4 3 1 5 1
9 1 1 1 -4 2
5 16
8 7 8 4 -1
1 6 6 7 9
5 7
1 1 -1 -2 8
7 -5 9 3 1
6 6
5 8 -2 8 5 -4
7 -5 5 1 5 -2
4 15
-3 3 5 8
-3 10 7 -3

输出

14
23
10
21
13

 

解题思路

  本质上就是选出若干个互不相交的区间,使得这些区间的 ai 总和最大。其中对于每个区间 [li,ri] 要满足 ri1+1<li(否则第 i1 个区间与第 i 个区间可以合并成一个区间),且每个区间关于 bi 的任意一个前缀的和不可以超过 m,即 j=likbjm,k[li,ri]

  考虑 dp,定义 f(i) 表示从前 i 天选出的所有合法区间中喜悦值的最大值,根据是否以第 i 天作为区间的右端点进行状态转移。状态转移方程为

f(i)=max{f(i1),maxjS{f(j1)+saisaj}}

  其中 sai=j=1iajS 表示满足以下要求的下标 j 的集合:

  • 0j<i
  • 定义 sbi=j=1ibj,则 k[j+1,i]sbksbjm

  显然直接暴力转移的话时间复杂度是 O(n3) 的。如果 j 满足条件,那么对于每个 k[j+1,i] 对应的  sbksbj+m。因此我们可以先通过 RMQ 维护关于 sbi 的区间最大值,在枚举 j 时,如果区间 [j+1,i] 内的 sbk 的最大值不超过 sbj+m,那么就可以从 j 处转移过来,这样时间复杂度就降到了 O(n2)

  如果要优化到 O(n) 意味着不能枚举 j 了。反过来思考,对于每个 j 如果以 j+1 作为区间的左端点,能不能求出右端点最远可以到达哪里?这是可以的,我们可以二分出这个右端点,对于二分点 mid,check 的时候只需判断区间 [j+1,mid] 内的 sbk 的最大值是否不超过 sbj+m。不过在代码实现中,二分出来的是不满足条件的最小位置,也就是最远合法右端点的下一个位置(不存在则设为 n+1)。

  这样在从小到大枚举 i 时,开一个 std::multiset 集合维护 j[0,i1] 关于 f(j1)saj 的最大值。对于合法右端点小于 i 的位置 j,需要将 f(j1)saj 从集合中删掉。设当前集合中的最大值为 x,则 f(i)=max{f(i1),x+sai}

  AC 代码如下,时间复杂度为 O(nlogn)

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

typedef long long LL;

const int N = 2e5 + 5;

LL sa[N], sb[N];
LL g[18][N];
vector<int> p[N];
LL f[N];

LL query(int l, int r) {
    int t = __lg(r - l + 1);
    return max(g[t][l], g[t][r - (1 << t) + 1]);
}

void solve() {
    int n;
    LL m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> sa[i];
        sa[i] += sa[i - 1];
    }
    for (int i = 1; i <= n; i++) {
        cin >> sb[i];
        sb[i] += sb[i - 1];
    }
    sb[n + 1] = 0x3f3f3f3f3f3f3f3f;
    for (int i = 0; 1 << i <= n + 1; i++) {
        for (int j = 1; j + (1 << i) - 1 <= n + 1; j++) {
            if (!i) g[i][j] = sb[j];
            else g[i][j] = max(g[i - 1][j], g[i - 1][j + (1 << i - 1)]);
        }
    }
    for (int i = 1; i <= n + 1; i++) {
        p[i].clear();
    }
    for (int i = 0; i < n; i++) {
        int l = i + 1, r = n + 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (query(i + 1, mid) > sb[i] + m) r = mid;
            else l = mid + 1;
        }
        p[l].push_back(i);
    }
    multiset<LL> st;
    for (int i = 1; i <= n; i++) {
        st.insert(f[max(0, i - 2)] - sa[i - 1]);
        for (auto &x : p[i]) {
            st.erase(st.find(f[max(0, x - 1)] - sa[x]));
        }
        f[i] = f[i - 1];
        if (!st.empty()) f[i] = max(f[i], *st.rbegin() + sa[i]);
    }
    cout << f[n] << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}


参考资料

  题解 | #环形取数#_牛客博客:httpsblog.nowcoder.netn0aad26a6e07e4e49a85c058b878cc03e

posted @   onlyblues  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-11-20 G. Restore the Permutation
2022-11-20 Number of Beautiful Partitions
2022-11-20 排队
Web Analytics
点击右上角即可分享
微信分享提示