CF1796D 做题笔记
一眼题,但这个
由于我初始的思路没考虑
考虑任意一个是最优答案的最大子段和,如果它的长度
小于
然后枚举这个答案的左端点之后,将左端点右边
该过程可以用线段树维护,时间复杂度为
代码:
#include <bits/stdc++.h> #define int long long #define For(i, a, b) for (int i = (a); i <= (b); i ++) #define foR(i, a, b) for (int i = (a); i >= (b); i --) using namespace std; int n, k, x, ans = 0; int c[200005]; struct S {int lmx, rmx, sum, mx;}a[800005]; void merge (S &a, S b, S c) { a.lmx = max (b.lmx, b.sum + c.lmx); a.rmx = max (c.rmx, c.sum + b.rmx); a.mx = max (max (b.mx, c.mx), b.rmx + c.lmx); a.sum = b.sum + c.sum; } void build (int l, int r, int k) { if (l == r) { a[k].lmx = a[k].rmx = a[k].sum = a[k].mx = c[l]; return; } int mid = l + r >> 1; build (l, mid, k << 1); build (mid + 1, r, k << 1 | 1); merge (a[k], a[k << 1], a[k << 1 | 1]); } void update (int l, int r, int k, int x, int y) { if (l == r) { a[k].lmx += y; a[k].rmx += y; a[k].sum += y; a[k].mx += y; return; } int mid = l + r >> 1; if (x <= mid) update (l, mid, k << 1, x, y); else update (mid + 1, r, k << 1 | 1, x, y); merge (a[k], a[k << 1], a[k << 1 | 1]); } void solve () { cin >> n >> k >> x; if (x < 0) { x = -x; k = n - k; } ans = 0; For (i, 1, n) { cin >> c[i]; if (i <= k) c[i] += x; else c[i] -= x; } build (1, n, 1); For (i, 1, n - k + 1) { if (i - 1) { update (1, n, 1, i - 1, -2 * x); update (1, n, 1, i + k - 1, 2 * x); } ans = max (ans, a[1].mx); } cout << ans << '\n'; } signed main () { int _ = 1; cin >> _; while (_ --) { solve (); cout << '\n'; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异