P2710 数列/P2042 [NOI2005] 维护数列

news/2024/9/20 1:43:26/文章来源:https://www.cnblogs.com/Yuan-Jiawei/p/18419323

题意(以 P2710 为例)

image

思路

使用 FHQ-Treap 进行求解,清晰明了。

  1. 对于 insert,先将要插入的数建成一棵树,然后将这棵树放入 FHQ-Treap 中。
  2. 对于 delete,将要删除的树分离出来,然后把剩下的部分合并即可,将删除的树的树根丢到废弃节点的栈中以备以后使用(节约空间,不然 MLE)。
  3. 对于 reverse,给一个节点打上标签并立即交换,参考文艺平衡树代码。注意,如果存在 MAKE-SAME 操作的标签,那么不用反转,因为所有数字都是一样的。
  4. 对于 make-same,将这个节点的 reverse 的标记清空(用不到,理由如上),给这个节点打上标记并立即更新结构体中所有数字。
  5. 对于 get-sum,pushup 维护即可。
  6. 对于 get,与普通平衡树的看排名为 \(x\) 的数字是什么类似。
  7. 对于 max-sum,最大子段和,参考 GSS-1,注意这是平衡树,对于根节点的处理细节非常多。

代码

细节非常多,注意对废弃节点的处理。(代码以 P2710 为准)

#include <bits/stdc++.h>using namespace std;
using i64 = long long;const int N = 500010;
const i64 inf = 1e18;struct node {int l, r, size, rnd;int tag_same, tag_rev;i64 key, lsum, rsum, sum, ans;
} tr[N];int rt, cnt;
int del_ver[N], top;
int n, m;
int a[N], sz_a;int newnode(int key) {int idx;if (!top) idx = ++cnt;else {idx = del_ver[top];top--;if (tr[idx].l) del_ver[++top] = (tr[idx].l);if (tr[idx].r) del_ver[++top] = (tr[idx].r);}tr[idx].l = tr[idx].r = 0;tr[idx].rnd = rand();tr[idx].size = 1;tr[idx].tag_same = -1e9;tr[idx].tag_rev = 0;tr[idx].key = tr[idx].lsum = tr[idx].rsum = tr[idx].sum = tr[idx].ans = key;return idx;
}void addtagrev(int u) {if (!u) return;if (tr[u].tag_same != -1e9) return;tr[u].tag_rev ^= 1;swap(tr[u].l, tr[u].r);swap(tr[u].lsum, tr[u].rsum);
}void addtagsame(int u, int key) {if (!u) return;if (tr[u].tag_rev) tr[u].tag_rev = 0;tr[u].tag_same = tr[u].key = key;tr[u].sum = key * tr[u].size;tr[u].lsum = tr[u].rsum = tr[u].ans = max(tr[u].key, tr[u].sum);
}void pushdown(int u) {if (tr[u].tag_same != -1e9) {tr[u].tag_rev = 0;addtagsame(tr[u].l, tr[u].tag_same);addtagsame(tr[u].r, tr[u].tag_same);tr[u].tag_same = -1e9;}if (tr[u].tag_rev) {addtagrev(tr[u].l);addtagrev(tr[u].r);tr[u].tag_rev = 0;}
}void pushup(int u) {tr[u].size = tr[tr[u].l].size + tr[tr[u].r].size + 1;tr[u].lsum = max({tr[tr[u].l].lsum, tr[tr[u].l].sum + tr[u].key, tr[tr[u].l].sum + tr[tr[u].r].lsum + tr[u].key});tr[u].rsum = max({tr[tr[u].r].rsum, tr[tr[u].r].sum + tr[u].key, tr[tr[u].r].sum + tr[tr[u].l].rsum + tr[u].key});tr[u].sum = tr[tr[u].l].sum + tr[tr[u].r].sum + tr[u].key;tr[u].ans = max({tr[tr[u].l].ans, tr[tr[u].r].ans, tr[u].key, tr[tr[u].l].rsum + tr[u].key, tr[tr[u].r].lsum + tr[u].key, tr[tr[u].l].rsum + tr[u].key + tr[tr[u].r].lsum});
}void split(int u, int sz, int &x, int &y) {if (!u) {x = y = 0;return;}pushdown(u);if (tr[tr[u].l].size + 1 <= sz) {x = u;split(tr[u].r, sz - tr[tr[u].l].size - 1, tr[u].r, y);}else {y = u;split(tr[u].l, sz, x, tr[u].l);}pushup(u);
}int merge(int x, int y) {if ((!x) || (!y)) return x | y;if (tr[x].rnd < tr[y].rnd) {pushdown(x);tr[x].r = merge(tr[x].r, y);pushup(x);return x;}else {pushdown(y);tr[y].l = merge(x, tr[y].l);pushup(y);return y;}
}void del(int l, int r) {int x, y, z;split(rt, r, x, z);split(x, l - 1, x, y);del_ver[++top] = (y);rt = merge(x, z);
}int build(int l, int r) {if (l == r) return newnode(a[l]);int mid = (l + r) >> 1;int x = build(l, mid);int y = build(mid + 1, r);return merge(x, y);
}void insert(int p) {int x, y;int rt2 = build(1, sz_a);split(rt, p, x, y);rt = merge(merge(x, rt2), y);
}void make_same(int l, int r, int c) {int x, y, z;split(rt, r, x, z);split(x, l - 1, x, y);addtagsame(y, c);rt = merge(merge(x, y), z);
}void reverse_arr(int l, int r) {int x, y, z;split(rt, r, x, z);split(x, l - 1, x, y);addtagrev(y);rt = merge(merge(x, y), z);
}i64 get_sum(int l, int r) {int x, y, z;split(rt, r, x, z);split(x, l - 1, x, y);i64 ans = tr[y].sum;rt = merge(merge(x, y), z);return ans;
}i64 get_max(int l, int r) {int x, y, z;split(rt, r, x, z);split(x, l - 1, x, y);i64 ans = tr[y].ans;rt = merge(merge(x, y), z);return ans;
}int get_num(int u, int rk) {pushdown(u);if (tr[tr[u].l].size + 1 == rk) return tr[u].key;else if (tr[tr[u].l].size >= rk) return get_num(tr[u].l, rk);else return get_num(tr[u].r, rk - tr[tr[u].l].size - 1);
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cin >> n >> m;tr[0].lsum = tr[0].rsum = tr[0].ans = -inf;for (int i = 1; i <= n; i++) cin >> a[i];sz_a = n;insert(0);string opt;int x, y, z;for (int T = 1; T <= m; T++) {cin >> opt;if (opt == "INSERT") {cin >> x >> sz_a;for (int i = 1; i <= sz_a; i++) cin >> a[i];insert(x);}else if (opt == "DELETE") {cin >> x >> y;del(x, x + y - 1);}else if (opt == "MAKE-SAME") {cin >> x >> y >> z;make_same(x, x + y - 1, z);}else if (opt == "REVERSE") {cin >> x >> y;reverse_arr(x, x + y - 1);}else if (opt == "GET-SUM") {cin >> x >> y;cout << get_sum(x, x + y - 1) << '\n';}else if (opt == "GET") {cin >> x;cout << get_num(rt, x) << '\n';}else {cin >> x >> y;cout << get_max(x, x + y - 1) << '\n';}}return 0;
}

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

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

相关文章

扩展分析C语言单双引号、反斜杠与注释

目录注释奇怪的注释C风格的注释无法嵌套一些特殊的注释注释的规则建议反斜杠\反斜杠有续行的作用,但要注意续行后不能添加空格回车也能起到换行的作用,那续行符的意义在哪?反斜杠的转义功能单引号和双引号字面值,字符串,字符,字符变量的大小为什么sizeof(1)的大小是4 ?char…

扩展分析单双引号、反斜杠与注释

目录注释奇怪的注释C风格的注释无法嵌套一些特殊的注释注释的规则建议反斜杠\反斜杠有续行的作用,但要注意续行后不能添加空格回车也能起到换行的作用,那续行符的意义在哪?反斜杠的转义功能单引号和双引号字面值,字符串,字符,字符变量的大小为什么sizeof(1)的大小是4 ?char…

C----函数递归之反汇编

环境 win10 vc6.0 debug 代码 关于求阶层问题:n!=n(n-1)!;(n-1)! = (n-1)(n-2)! 例如5!=5(4)! 4!=43! 3!=32! 2!=21 函数递归的出口是1,所以函数递归最重要的条件是去寻找递归的出口 int fun(int i) {int sum = 0;if (i == 1){return 1;}else{sum = i*fun(i-1);}return sum …

地平线占用预测 FlashOcc 参考算法-V1.0

1.简介 3D Occupancy Networks 的基本思路是将三维空间划分成体素网格,并对每个网格进行各类感知任务的预测。目前以网格为中心的方法能够预测每个网格单元的占用率、语义类别、未来运动位移和实例信息。3D occupancy 可以对道路障碍物进行更细粒度的划分,同时获取更精确的占…

手脱upx

其实已经是大一下刚开始的事情了,补个档 手动脱壳の新年快乐 查壳,有壳,UPXX32dbg打开文件,查看初始断点点击PUSHAD跟进,CTRL+*设置EIP,开始F8步过,寻找ESP寄存器第一次单个变红的地址此时的内存窗口开始步过第一次步过就发现ESP单个变红,右键跟进内存窗口然后在第一个…

使用firemin降低火狐内存占用

这些年一直使用火狐浏览器,之前一直在AMD平台的机器使用,没有遇到过内存占用过大的问题(可能也与平台无关)。现在在Intel CPU的机器上使用,时间一久,内存就占用很大。试过Firefox/内存消耗严重里面的办法,效果不明显。也试过修改about:config里面的一些选项,也没有达到…

代码随想录算法 - 回溯算法1

题目1 77. 组合 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入:n = 4, k = 2 输出: [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ]示例 2: 输入:n = 1, k = 1 输出:[[1]]提示:1 <= n <= 20 1 <= k…

错误

PID自己搭的时候,要注意积分模块的位置,搞不明白好久了,原来是我把积分模块的位置放错了。直接用增益模块不容易出错。

OSG开发笔记(三十):OSG加载动力学仿真K模型文件以及测试Demo

前言Osg需要打开模型文件,但是遇到显示动力学仿真的K模型文件,.k文件是一种描述材料属性的文件,比如密度、弹性模量等,该模型文件不是常规中间开放格式,无法直接支持,需要自定义解析并且重建三维模型。 Demo实际非常流程,因为视频转gif导致部分看起来不行:   交互流畅…

0918高数一千题,多元函数积分学

T17.第一型曲线积分空间形式 用斯托克斯公式化成第二型曲面积分 解第二型曲面积分,用高斯公式或者投影转换法,后者注意正负号,上正下负,前正后负 T18.换路径,但是x=1左半段不能化成lnx算 T19.求偏导就对对应字母求就行,不用对y导x T20.多元极值AC-B2>0A>0,极小 A<…

Dynamic Locomotion in the MIT Cheetah 3 Through Convex Model-Predictive Control

1. Swing Leg Control\(J_i \in R^{3*3}\) 是足端雅可比;\(\tau _{i,ff}\) 是前馈力矩 \(\Lambda \in R^{3*3}\)是操作空间惯性矩阵;\(a_{i,ref} \in R^{3*3}\)是机体坐标系下的参考加速度 q是关节角度;\(C_i \dot{q}_i + G_i\)是科里奥利力和重力 2. Ground Force Control …