题解:Luogu P13544 [OOI 2022] Serious Business

news/2025/10/20 22:04:07/文章来源:https://www.cnblogs.com/P2441M/p/19153776

题意

给定一个 \(3\times n\) 的网格,每个格子 \((i,j)\) 内有一个数 \(a_{i,j}\)。一个人初始分数为 \(0\),在位置 \((1,1)\) 处,每次可以向右或向下走一格,目标是到达 \((3,n)\)。当走到格子 \((i,j)\) 时,这个人的分数会增加 \(a_{i,j}\)

起初,只有第一、三行的格子是可用的。现在给出了 \(q\) 个区间 \([l_i,r_i]\)\(k_i\),表示这个人可以减少 \(k_i\) 的得分让第二行第 \(l_i\)\(r_i\) 个格子变得可用。求达成目标的最大得分。\(1\leq n,q\leq 5\times 10^5\)\(-10^9\leq a_{i,j}\leq 10^9\)\(1\leq k_i\leq 10^9\)

题解

下文中令 \(s_{i,j}=\sum_{k=1}^ja_{i,k}\)

考虑 DP。令 \(f_i\) 表示从 \((1,1)\) 走到 \((2,i)\)钦定 \(i\) 是某个区间的右端点的最大得分。我们从小到大枚举 \(i\),遍历所有右端点为 \(i\) 的区间 \([l,i]\),考虑其转移:

  • 从前面某个区间的右端点对应的 \((2,j)\) 向右走到 \((2,i)\)

    \[f_i\leftarrow \max_{l-1\leq j\leq i-1}\{f_j-s_{2,j}\}+s_{2,i}-k \]

  • \((1,j)\) 向下走到区间内的 \((2,j)\),然后向右走到 \((2,i)\)

    \[f_i\leftarrow \max_{l\leq j\leq i}\{s_{1,j}-s_{2,j-1}\}+s_{2,i}-k \]

后者显然是 RMQ,可以使用 ST 表维护。前者也可以用线段树维护 \(f_j-s_{2,j}\) 的区间 \(\max\),不过我们注意到 \(>i\) 的部分是没有有效值的,所以实际上是后缀询问,可以使用 BIT 维护。

考虑如何统计答案。问题在于,从第二行走到第三行的拐点,不一定在某个区间的右端点上。但是我们可以发现,在第二行解锁的区间中,最多只有一个区间的右端点没有被走到。因为如果有多个没走满的区间,我们显然可以删掉左端点最大的那个。于是我们枚举没走满的区间 \([l,r]\),做和前面类似的分类讨论:

  • 从前面某个区间的右端点对应的 \((2,i)\) 走到 \((2,j)\)

    \[\begin{align*} ans&\leftarrow \max_{l-1\leq i\leq j\leq r}\{f_i+s_{2,j}-s_{2,i}+s_{3,n}-s_{3,j-1}\}\\ &=\max_{l-1\leq i\leq j\leq r}\{(f_i-s_{2,i})+(s_{2,j}-s_{3,j-1})\}+s_{3,n} \end{align*} \]

  • \((1,i)\) 向下走到 \((2,i)\),再向右走到 \((2,j)\)

    \[\begin{align*} ans&\leftarrow \max_{l\leq i\leq j\leq r}\{s_{1,i}+s_{2,j}-s_{2,i-1}+s_{3,n}-s_{3,j-1}\}\\ &=\max_{l-1\leq i\leq j\leq r}\{(s_{1,i}-s_{2,i-1})+(s_{2,j}-s_{3,j-1})\}+s_{3,n} \end{align*} \]

两者都是形如区间查询 \(\max_{l\leq i\leq j\leq r}\{A(i)+B(j)\}\) 的形式,可以使用线段树维护,在节点上维护区间的 \(A,B\) 最大值和 \(\max_{l\leq i\leq j\leq r}\{A(i)+B(j)\}\) 即可。

时间复杂度 \(\mathcal{O}((n+q)\log{n})\)

代码

#include <bits/stdc++.h>using namespace std;#define lowbit(x) ((x) & -(x))
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5e5 + 5;
const ll INF = 1e18;namespace IO {const int S = 1 << 24, lm = 1 << 23;char bi[S + 5], *p1 = bi, *p2 = bi, ch;int s;#define gc() (p1 == p2 && (p2 = (p1 = bi) + fread(bi, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)inline ll rd() {s = 1; char ch;while (ch = gc(), (ch < '0')) if (ch == '-') s = -1;ll x = ch ^ 48;while (ch = gc(), (ch >= '0')) x = (x << 3) + (x << 1) + (ch ^ 48);return s == 1 ? x : -x;}
}
using IO::rd;template<typename T> inline void chk_min(T &x, T y) { x = min(x, y); }
template<typename T> inline void chk_max(T &x, T y) { x = max(x, y); }int n, m, a[3][N];
ll val1[N], val2[N];
ll ans = -INF, pre[3][N], f[N];
struct Range { int l, r, k; } rg[N];
basic_string<Range> vec[N];struct BIT {ll c[N];inline void init() { fill(c + 1, c + n + 1, -INF); }inline ll query(int x) {ll res = -INF;for (; x <= n; x += lowbit(x)) chk_max(res, c[x]);return res;}inline void upd(int x, ll v) { for (; x; x -= lowbit(x)) chk_max(c[x], v); }
} ft1, ft2;
struct SegTree2 {
#define ls(p) (p << 1)
#define rs(p) (p << 1 | 1)struct Node {ll mx1, mx2, dat;Node() : mx1(-INF), mx2(-INF), dat(-INF) {}Node(ll mx1, ll mx2, ll dat) : mx1(mx1), mx2(mx2), dat(dat) {}Node operator+(const Node &x) const { return {max(mx1, x.mx1), max(mx2, x.mx2), max({dat, x.dat, mx1 + x.mx2})}; }} nodes[N << 2];inline void push_up(int p) { nodes[p] = nodes[ls(p)] + nodes[rs(p)]; }inline void build(int p, int l, int r) {if (l == r) return nodes[p] = {val1[l], val2[l], val1[l] + val2[l]}, void();int mid = l + r >> 1;build(ls(p), l, mid), build(rs(p), mid + 1, r);push_up(p);}inline Node query(int p, int l, int r, int x, int y) {if (x <= l && y >= r) return nodes[p];int mid = l + r >> 1; Node res;if (x <= mid) res = query(ls(p), l, mid, x, y);if (y > mid) res = res + query(rs(p), mid + 1, r, x, y);return res;}
#undef ls
#undef rs
} sgt3;int main() {ios::sync_with_stdio(0), cin.tie(0);n = rd(), m = rd();for (int i = 0; i < 3; ++i) for (int j = 1; j <= n; ++j) a[i][j] = rd(), pre[i][j] = pre[i][j - 1] + a[i][j];for (int i = 1, l, r, k; i <= m; ++i) l = rd(), r = rd(), k = rd(), vec[r] += rg[i] = {l, r, k};fill(f + 1, f + n + 1, -INF), ft1.init(), ft2.init();for (int i = 1; i <= n; ++i) {ft2.upd(i, pre[0][i] - pre[1][i - 1]);for (Range it : vec[i]) {int l = it.l, k = it.k;if (i > 1) chk_max(f[i], ft1.query(max(l - 1, 1)) + pre[1][i] - k);chk_max(f[i], ft2.query(l) + pre[1][i] - k);}ft1.upd(i, f[i] - pre[1][i]);}for (int i = 1; i <= n; ++i) val1[i] = f[i] - pre[1][i], val2[i] = pre[1][i] - pre[2][i - 1];sgt3.build(1, 1, n);for (int i = 1; i <= m; ++i) chk_max(ans, sgt3.query(1, 1, n, max(rg[i].l - 1, 1), rg[i].r).dat + pre[2][n] - rg[i].k);for (int i = 1; i <= n; ++i) val1[i] = pre[0][i] - pre[1][i - 1];sgt3.build(1, 1, n);for (int i = 1; i <= m; ++i) chk_max(ans, sgt3.query(1, 1, n, rg[i].l, rg[i].r).dat + pre[2][n] - rg[i].k);cout << ans;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/941659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

题解:Luogu P14254 分割(divide)

题意 给定一棵 \(n\) 个点的树,设根节点 \(1\) 的深度为 \(1\)。给定 \(k\),求有多少从树中选出 \(k\) 个两两不同的节点,组成有序序列 \(b_1,\cdots,b_k\) 的方案,使得:对于每个 \(1\leq i<k\),\(1<d_{b_…

31_创蓝短信接入资料和定价

创蓝短信接入资料和定价 公司简介 创蓝云智为企业提供短信、语音外呼、闪验、号码检测、实名认证等通讯类产品,致力于让企业更高效高质量的获得用户及触达用户。 产品类型通知短信 会员营销短信 国际营销短信 验证码短…

构造单

题目来源 取模下序列构造 是否存在 \(3\) 个长度为 \(n\) 的 \([0,n)\) 的排列 \(a,b,c\),使得 \(a_i+b_i=c_i\mod n\) 遇到取模考虑奇偶性,不要像太复杂,考虑 \(n\) 为奇数的时候直接 \(a=b=~0,1,2,3,4,…\),\(c=…

02.Python百行代码实现抽奖系统

02.Python百行代码实现抽奖系统 ------------------------------------------------ 执行后——————————————————————————————————————————————————————————…

[笔记]高斯消元

高斯消元法是求解线性方程组的经典算法。 内容 求解如下的线性方程组(P3389 【模板】高斯消元法): \[\begin{cases} a_{1,1}x_1+a_{1,2}x_2+\dots+a_{1,n}x_n=b_1\\ a_{2,1}x_1+a_{2,2}x_2+\dots+a_{2,n}x_n=b_2\\ …

[SSH] scp:基于 SSH 的安全文件传输

[SSH] scp:基于 SSH 的安全文件传输$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");目录01 简介02 操作2.1 本地发送到远程2.2 从远程下载2.3 主机之间复制…

CSP-S 35

10.2010.20 神秘%你赛,rk1 170 ,你管这叫CSP-S? t1 赛时狂写t1 ,想了半天想出来个神秘做法,时间复杂度不会证但应该是对的,写完本地大阳历1.2s 感觉应该没啥大问题,结果空间炸了,最后2h写的代码和暴力分一样多 …

题解:P11662 [JOI 2025 Final] 方格染色 / Grid Coloring

题目传送门 是一道黄题 这里提供一种 \(O(n\log n)\) 的做法\(\mathscr{PART\ \ ONE}\)我们在手%的时候不难发现(注意力有点也不惊人) 虽然第一列和第一行 不保证有序 但是因为这里的前缀$\ max\ $性质保证了第二列和…

CSP-S 32 多校5

10.1510.15 S-32&&多校5 签到后遗憾离场。 t1 签到题,大力分讨即可。 注意符号。 记得排序(没大阳历时忘排序了) code锵锵 #include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10;…

CSP-S 33

10.1710.17 t1 签到题 注意到约数只有 \(O(\sqrt n)\) 级别,暴力找约数即可。 唐人当然有唐做法啦! 分解质因数+dfs搜约数 反正唐就对了。 code嘻嘻 #include <bits/stdc++.h> #define int long long #define…

CSP-S 29

10.11 只记录了当时认为有意义的题10.11 t3 赛后才看懂题面 \(\ldots\) 妈妈我会推式子!(骗你的其实我不会) 推完式子就过了。 考虑先求出 \(1\) 为根时的答案,之后换根即可。 开始拆贡献ing 对于根结点,由于一开…

10.20每日总结

今天主要的课程有软件设计,软件开发案例分析,大数据技术,物联网工程。完成了好几项作业,满课还是太忙太累了,软考网课开始第三章。

CSP-S 31

10.1410.14 看大家得分跟信心赛似的,就我一个唐诗写了一场暴力 \(\ldots\) 开场t1没切出来就开始慌了,之后就想着多打暴力拿部分分,导致t2得出的性质没有推广,t3,t4暴力都没写出来(这俩得出性质/部分性质后比暴力…

2025网络安全振兴杯wp

振兴杯wp web1 神探狄仁杰在js和源代码,以及关于里面有flag的base64字段 css中关于的源代码中然后解密就行了 web2Darksale 这个是一个原型链污染 我们发现购买的金额可以被改变我们发现改价格后会回显出来我们尝试修…

ES原理、zookeeper、kafka

ES原理、zookeeper、kafkaES高级 ES底层原理 协调节点是 Elasticsearch 中接收客户端请求、将请求转发到相关数据节点、并汇总最终结果返回给客户端的中心路由节点 Cluster State 是 Elasticsearch 集群的元数据大脑,…

CF1606E Arena 题解(动态规划)

考虑设 \(f_{i,j}\) 表示现在存活 \(i\) 个人,血量最大的人为 \(j\)。这么设是因为注意到有没有胜者其实之和血量最大的是谁,以及有多少个血量最大的有关。 边界情况 \(f_{1,i}=0\)。 考虑转移。如果 \(j<i\),则…

服务器CPU市场概况2025

2025年的服务器CPU市场正处于关键转型期。传统的x86架构(以Intel和AMD为代表)依然占据主导,但基于Arm的解决方案正在快速崛起。随着人工智能(AI)、云计算和高性能计算(HPC)的普及,CPU的设计趋势正在朝着能效优…

CSP-S 24

9.21~9.2?9.21 今天开始集训告一段落了,去补文化课一周。 如果写不完回来会补(?) 115=100+0+15 t1 先等会 t2 先等会 t3 9.22:回来补债了 \([\gcd(i,j)=1]=[\gcd(p_i,p_j)=1]\) 这个限制初看好像很难转化,只能猜…

正睿 2025 NOIP20 连测 Day5 做题记录

T1给 \(m\) 个质数,第 \(i\) 个质数 \(p_i\) 出现了 \(n_i\) 次。求一种划分质数的方案,使得第一个集合的和等于第二个集合的乘积。萌萌题,注意到最后相当于是要求 \(p_1^{\alpha_1}p_2^{\alpha_2}\cdots p_k^{\alp…