CF739C Alyona and towers 解题报告
线段树绝世好题。
题意:
维护区间加,全局最长单峰序列。
Solution:
维护 个量。
:左端点的权值。
:右端点的权值。
:以左端点开始的最长的下降序列长度。
:以右端点结束的最长的上升序列长度。
:以左端点开始的最长的单峰序列长度。
:以右端点结束的最长的单峰序列长度。
: 区间内最长的单峰序列长度。
:区间加法懒标记。
考虑怎么用左右两个儿子更新父节点的信息。
用 来表示左儿子, 来表示右儿子, 来表示父节点。
显然父节点的 是左儿子的 。
显然父节点的 是右儿子的 。
如果说左儿子的 等于左儿子的区间长度,说明了左区间是个下降区间,如果同时左儿子的 大于了右儿子的 说明了父节点的 能向右区间伸展,这个时候 。
否则无法跨过右区间,直接继承左儿子的值:。
如果说右儿子的 等于右儿子的区间长度,说明了右区间是个上升区间,如果同时左儿子的 小于了右儿子的 说明了父节点的 能向左区间伸展,这个时候 。
否则无法跨过左区间,直接继承右儿子的值: 。
如果说左儿子的 等于左儿子的区间长度,说明了左儿子是个上升区间。
这个时候分两种情况:
- 说明了还能通过右儿子的 继续扩展:。
- 说明了只能通过右儿子的 继续扩展: 。
如果说左儿子的 等于区间长度,想用右儿子扩展的话,必须满足 ,这个时候:。
否则无法通过右区间来更新,直接继承左儿子的值:。
如果说右儿子的 等于右儿子的区间长度,说明了右儿子是个下降区间。
这个时候分两种情况:
-
说明了还能通过左儿子的 继续扩展:。
-
说明了只能通过左儿子的 继续扩展: 。
如果说右儿子的 等于区间长度,想用左儿子扩展的话,必须满足 ,这个时候:。
否则无法通过右区间来更新,直接继承左儿子的值:。
答案可能是左右儿子答案的最大值。
也可能是 和 接起来。
也可能是 和 接起来。
也可能是 和 接起来。
最后取个 就行了。
然后修改就是普通的区间修改。
/** * author: TLE_Automation * creater: 2022.8.28 **/ #include<cmath> #include<queue> #include<cstdio> #include<bitset> #include<cstring> #include<iostream> #include<algorithm> #define gc getchar #define INF 0x3f3f3f3f #define int long long using namespace std; typedef long long ll; const int Maxn = 6e5 + 10; const int mod = 998244353; const ll inf = 0x3f3f3f3f3f3f3f3f; #define debug cout << "i ak ioi" << "\n" inline void print(int x) {if (x < 0) putchar('-'), x = -x; if(x > 9) print(x / 10); putchar(x % 10 + '0');} inline char readchar() {static char buf[100000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;} inline int read() { int res = 0, f = 0; char ch = gc();for (; !isdigit(ch); ch = gc()) f |= (ch == '-'); for (; isdigit(ch); ch = gc()) res = (res << 1) + (res << 3) + (ch ^ '0'); return f ? -res : res;} namespace Seg { #define lson rt << 1 #define rson rt << 1 | 1 struct Node { int l, r, len, lval, rval, lmax, rmax, lans, rans, ans, tag; } tree[Maxn << 2]; void pushup(int rt) { tree[rt].lval = tree[lson].lval, tree[rt].rval = tree[rson].rval; if(tree[lson].lmax == tree[lson].len && tree[lson].rval > tree[rson].lval) tree[rt].lmax = tree[lson].lmax + tree[rson].lmax; else tree[rt].lmax = tree[lson].lmax; if(tree[rson].rmax == tree[rson].len && tree[rson].lval > tree[lson].rval) tree[rt].rmax = tree[rson].rmax + tree[lson].rmax; else tree[rt].rmax = tree[rson].rmax; if(tree[lson].rmax == tree[lson].len && tree[lson].rval < tree[rson].lval) tree[rt].lans = tree[lson].rmax + tree[rson].lans; else if(tree[lson].rmax == tree[lson].len && tree[lson].rval > tree[rson].lval) tree[rt].lans = tree[lson].rmax + tree[rson].lmax; else if(tree[lson].lans == tree[lson].len && tree[lson].rval > tree[rson].lval) tree[rt].lans = tree[lson].lans + tree[rson].lmax; else tree[rt].lans = tree[lson].lans; if(tree[rson].lmax == tree[rson].len && tree[rson].lval < tree[lson].rval) tree[rt].rans = tree[rson].rans + tree[lson].rans; else if(tree[rson].lmax == tree[rson].len && tree[rson].lval > tree[lson].rval) tree[rt].rans = tree[rson].rans + tree[lson].rmax; else if(tree[rson].rans == tree[rson].len && tree[lson].rval < tree[rson].lval) tree[rt].rans = tree[rson].rans + tree[lson].rmax; else tree[rt].rans = tree[rson].rans; tree[rt].ans = max(tree[lson].ans, tree[rson].ans); if(tree[lson].rval != tree[rson].lval )tree[rt].ans = max(tree[rt].ans, tree[lson].rmax + tree[rson].lmax); if(tree[lson].rval < tree[rson].lval) tree[rt].ans = max(tree[rt].ans, tree[lson].rmax + tree[rson].lans); if(tree[lson].rval > tree[rson].lval) tree[rt].ans = max(tree[rt].ans, tree[rson].lmax + tree[lson].rans); } void build(int rt, int l, int r) { tree[rt].len = r - l + 1; tree[rt].l = l, tree[rt].r = r; if(l == r) { int x = read(); tree[rt].lval = tree[rt].rval = x; tree[rt].lmax = tree[rt].rmax = 1; tree[rt].lans = tree[rt].rans = tree[rt].ans = 1; return; } int mid = (l + r) >> 1; build(lson, l, mid), build(rson, mid + 1, r); pushup(rt); } void pushdown(int rt) { if(!tree[rt].tag) return; tree[lson].tag += tree[rt].tag, tree[rson].tag += tree[rt].tag; tree[lson].lval += tree[rt].tag, tree[lson].rval += tree[rt].tag; tree[rson].lval += tree[rt].tag, tree[rson].rval += tree[rt].tag; tree[rt].tag = 0; } void change(int rt, int l, int r, int k) { if(tree[rt].l > r || tree[rt].r < l) return; if(tree[rt].l >= l && tree[rt].r <= r) { tree[rt].lval += k, tree[rt].rval += k, tree[rt].tag += k; return; } pushdown(rt); change(lson, l, r, k), change(rson, l, r, k), pushup(rt); } } using namespace Seg; signed main() { // freopen("in.in", "r", stdin); // freopen("baoli.out", "w", stdout); int n = read(); build(1, 1, n); int Q = read(); for(int i = 1; i <= Q; i++) { int l = read(), r = read(), k = read(); change(1, l, r, k), printf("%lld\n", tree[1].ans); } return (0 - 0); } /** * _ooOoo_ * o8888888o * 88" . "88 * (| -_- |) * O\ = /O * ___/`---'\____ * . ' \\| |// `. * / \\||| : |||// \ * / _||||| -:- |||||- \ * | | \\\ - /// | | * | \_| ''\---/'' | | * \ .-\__ `-` ___/-. / * ___`. .' /--.--\ `. . __ * ."" '< `.___\_<|>_/___.' >'"". * | | : `- \`.;`\ _ /`;.`/ - ` : | | * \ \ `-. \_ __\ /__ _/ .-` / / * ======`-.____`-.___\_____/___.-`____.-'====== * ` =---=' * ............................................. * 佛曰:bug泛滥,我已瘫痪! */
本文作者:TLE_Automation
本文链接:https://www.cnblogs.com/tttttttle/p/16643433.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】