『区间最值操作 & 区间历史最值』Day6
1 势能
1.1
有一类之前就见过的操作。区间取模区间开方。
开方是说在
取模则是说如果一个数能取模那么至少会减少一半,所以一个数最多暴力操作
上面的复杂度都是
1.2
区间开方,区间加,查询区间和。
为什么要按照
因为我们直接用标记处理
而每个区间暴力最多次数还是
区间加,区间除,查询区间和,查询区间 min。
还是 max - min,考虑暴力复杂度。
因为你区间加是不会让 max - min 增多的,是
1.3
尝试对上面的情况进行总结。
你设置一个分界情况,一边暴力,一边打标记(且可以打标记);
只需要保证暴力的复杂度正确。
可以完成 T1。
查看他人代码发现没有处理区间覆盖,因为这种情况存在当且仅当之前
而之前的势能一共是
2 最值
结论:维护 Max, SecondMax;每次如果 Mintag < SecondMax 就暴力向下修改,否则可以直接改 Max。
感觉分析很乱,也许我曾经证出过,记结论。
3 历史版本
3.1
维护历史标记和当前标记,下传的时候子节点一定没有被这些标记标记过。(每次 pushup、pushdown 都需要传历史最值和当前)
更新的时候就把父亲的标记
说到标记,你可以把它写成多原组的形式,重定义广义下的 + 和 max。
注意,+ 不一定满足交换律;但一定满足结合律。
3.2
两种标记叠加的情况。
如果你同时有加法和覆盖标,标记都是加法,突然来了一个乘法;那么接下来你维护的标记就不能有加法了,直接把覆盖标加上即可。
4 习题
Picks hates segment tree
为什么还支持加法啊。
因为你一次减少势能使得 maxn 和 sex 消失了一个,而加法不会影响相对大小。
V
标记的广义运算。放代码上来:
struct sb {
int x, y;
sb () {}
sb (int _, int __ ) { x = _, y = __; }
sb operator + (sb t) { return sb(x + t.x, Max(y + t.x, t.y)); }
};
sb max(sb x, sb y) { return sb(Max(x.x, y.x), Max(x.y, y.y)); }
struct node {
sb _, a;
} T[N << 2];
void upd(int p, sb _, sb t) { // 看成是,从父亲节点传下来的,历史最大值,和现在的 tag
T[p]._ = max(T[p]._, T[p].a + _); T[p].a = T[p].a + t;
}
序列
莫队移动。
可以按照最小值的区间线性 dp 计算,注意先考虑不规整的那一段。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现