前后缀分解
1.前后缀分解
2.【前缀和+开区间二分】codeforces 1187 B. Letters Shop3.【字符串哈希+二分】AcWing 3508. 最长公共子串4.【二分+前缀和+后缀和】codeforces 2026 D. Sums of Segments5.【滑动窗口】codeforces 1290 A. Mind Control6.【三分】AcWing 3666. 士兵排阵7.【带权前缀和】codeforces 2044 H. Hard Demon Problem8.【区间合并+贡献法】codeforces 1789 C. Serval and Toxel's Arrays9.【离线+单调栈】AtCoder ABC379 F. Buildings 2题型
给定一个数组(可以是高维度数组),若目标结果是求删掉数组中的一个元素后,剩余的全部元素进行运算的结果的最佳值,一般考虑前后缀分解。
若是求一个数组的子数组(子数组是指元素下标位置连续),也可以通过前后缀分解得到。任意一个子数组,都可以通过原数组减去一个前缀数组和一个后缀数组得到。
模板
for (int i = 1; i <= n; ++ i) { pre[i] = pre[i] + pre[i - 1]; } for (int i = n; i > 0; -- i) { post[i] = post[i] + post[i + 1]; } for (int i = 1; i <= n; ++ i) { val = pre[i - 1] + post[i + 1];//结构体可以重载+运算符 //对val值进行计算 }
例题
例题一:Maximal intersection
题目链接:https://codeforces.com/problemset/problem/1029/C
题目
题解
要求的结果就是扣去一个区间后剩余的全部区间的交集。因此,符合前后缀分解的使用场景。
求一次前缀区间交集与一次后缀区间交集,遍历一遍求前缀与后缀的交集的大小的最大值即可。
参考代码
C++
#include<bits/stdc++.h> #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); using namespace std; int n, ans; struct seg { int l, r; seg operator + (const seg& s) { seg _s; _s.l = max(this -> l, s.l); _s.r = min(this -> r, s.r); return _s; } }; int main() { IOS cin >> n; vector<seg> pre(n + 2), post(n + 2); pre[0].l = post[0].l = pre[n + 1].l = post[n + 1].l = 0; pre[0].r = pre[n + 1].r = post[0].r = post[n + 1].r = 1e9; for (int i = 1; i <= n; ++ i) { cin >> pre[i].l >> pre[i].r; post[i] = pre[i]; } for (int i = 1; i <= n; ++ i) { pre[i] = pre[i] + pre[i - 1]; } for (int i = n; i > 0; -- i) { post[i] = post[i] + post[i + 1]; } for (int i = 1; i <= n; ++ i) { pre[i - 1] = pre[i - 1] + post[i + 1]; ans = max(ans, pre[i - 1].r - pre[i - 1].l); } cout << ans << '\n'; return 0; }
例题二:Maximal intersection扩展题
题目
如果去掉一个区间 求的是剩下的全部区间的两两交集之和 最大能是多少?
题解
利用差分数组与前缀和实现,但由于数据范围大,数据量小,要么考虑离散化,要么考虑使用map去模拟差分,再结合前后缀分解,即可实现去掉一个区间,求剩下的全部区间的两两交集之和的最大值
例题三:不为 X 的倍数的最长子数组长度
题目链接:https://codeforces.com/problemset/problem/1364/A
参考代码:
C++
#include<bits/stdc++.h> using namespace std; using ll = long long; constexpr int N = 1e5 + 7; int T, n, x; int a[N]; ll pre[N], pst[N]; void solve() { cin >> n >> x; for (int i = 1; i <= n; ++ i) cin >> a[i]; if (x == 1) { cout << -1 << '\n'; return ; } int res = -1, last = -1; for (int i = 1; i <= n; ++ i) pre[i] = pre[i - 1] + a[i]; ll sum = pre[n]; if (sum % x) { cout << n << '\n'; return ; } pst[n + 1] = 0; for (int i = n; i >= 1; -- i) { pst[i] = pst[i + 1] + a[i]; if (pst[i] % x) { if (last == -1) last = i; res = n - i + 1; } } if (last != -1) { int num = n - last + 1; for (int i = 1; i <= n; ++ i) { if (pre[i] % x) res = max(res, i); else if (last > i) res = max(res, n - num); ll s = sum - pre[i]; if (s % x) res = max(n - i, res); else if (last > i) res = max(res, n - i - num); } } cout << res << '\n'; } int main() { ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr); cin >> T; while (T --) { solve(); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee