题面大意:

使用平衡树维护一个数列,支持插入,修改,删除,翻转,求和,求最大和这 \(6\) 个操作.

题意分析:

Splay 裸题,几乎各种操作都有了,这个代码就发给大家当个模板吧.

最后求最大和的时候可以事先维护好最大和,然后输出即可。

代码:

#include <cstdio>
#include <climits>
#include <algorithm>
#include <iostream>
#define maxn 1000001
using namespace std; int stack[maxn], top, v[maxn];
struct Splay {
#define T(x) (tree[f[x]][1]==x)
#define ls(x) tree[x][0]
#define rs(x) tree[x][1]
int tree[maxn][2], f[maxn], size[maxn], val[maxn];
int sum[maxn], L[maxn], R[maxn], Max[maxn];
bool rev[maxn], mark[maxn];
int root, len; void cov_tag(int x, int v) {
if (!x) return;
sum[x] = size[x] * v;
val[x] = v;
L[x] = R[x] = Max[x] = max(v, sum[x]);
mark[x] = 1, rev[x] = 0;
} void rev_tag(int x) {
if (!x) return;
swap(L[x], R[x]);
swap(ls(x), rs(x));
rev[x] ^= 1;
} void pushdown(int x) {
if (rev[x]) {
rev_tag(ls(x));
rev_tag(rs(x));
rev[x] = 0;
}
if (mark[x]) {
cov_tag(ls(x), val[x]);
cov_tag(rs(x), val[x]);
mark[x] = 0;
}
} void updata(int x) {
size[x] = size[ls(x)] + size[rs(x)] + 1;
Max[x] = max(max(Max[ls(x)], Max[rs(x)]), max(0, R[ls(x)]) + val[x] + max(0, L[rs(x)]));
L[x] = max(L[ls(x)], sum[ls(x)] + val[x] + max(0, L[rs(x)]));
R[x] = max(R[rs(x)], sum[rs(x)] + val[x] + max(0, R[ls(x)]));
sum[x] = sum[ls(x)] + sum[rs(x)] + val[x];
} int get() {
int x;
x = top ? stack[top--] : ++len;
ls(x) = rs(x) = f[x] = 0;
rev[x] = mark[x] = 0;
size[x] = 1;
sum[x] = L[x] = R[x] = val[x] = -1e9;
return x;
} void build(int fa, int l, int r, int& x) {
if (l > r) return;
int mid = (l + r) >> 1;
x = get(), f[x] = fa, val[x] = v[mid];
if (l == r) {
size[x] = 1;
Max[x] = L[x] = R[x] = sum[x] = val[x];
return;
}
build(x, l, mid - 1, ls(x));
build(x, mid + 1, r, rs(x));
updata(x);
} void init(int n) {
L[0] = R[0] = Max[0] = -1e9;
len = 2, root = 1;
rs(1) = size[1] = 2, L[1] = R[1] = val[1] = sum[1] = -1e9;
f[2] = size[2] = 1, L[2] = R[2] = val[2] = sum[2] = -1e9;
for (int i = 1; i <= n; i++) {
cin >> v[i];
}
build(2, 1, n, ls(2));
updata(2), updata(1);
} void move(int x) {
int fa = f[x], son = tree[x][T(x) ^ 1];
tree[x][T(x) ^ 1] = fa;
tree[fa][T(x)] = son;
if (son) f[son] = fa;
f[x] = f[fa];
if (f[x]) tree[f[x]][T(fa)] = x;
f[fa] = x;
updata(fa), updata(x);
} void splay(int x) {
while (f[x]) {
if (f[f[x]]) T(x) == T(f[x]) ? move(f[x]) : move(x);
move(x);
}
root = x;
} int find(int x, int i) {
pushdown(i);
if (size[ls(i)] + 1 == x) return i;
if (x <= size[ls(i)]) return find(x, ls(i));
return find(x - size[ls(i)] - 1, rs(i));
} void insert() {
int x, y, tot;
cin >> x >> tot;
x++;
y = x + 1;
x = find(x, root), splay(x);
y = find(y, root), splay(y);
if (f[x] != root) move(x);
for (int i = 1; i <= tot; i++) {
cin >> v[i];
}
build(x, 1, tot, rs(x));
updata(x), updata(y);
} void reuse(int x) {
if (!x) return;
stack[++top] = x;
reuse(ls(x)), reuse(rs(x));
} void Del() {
int x, y;
cin >> x >> y;
y = y + x - 1;
x = find(x, root), splay(x);
y = find(y + 2, root), splay(y);
if (f[x] != root) move(x);
reuse(rs(x));
f[rs(x)] = 0, rs(x) = 0;
updata(x), updata(y);
} void cover() {
int x, y, v;
cin >> x >> y >> v;
x = find(x, root), splay(x);
y = find(y + 2, root), splay(y);
if (f[x] != root) move(x);
cov_tag(rs(x), v);
updata(x), updata(y);
} void reverse() {
int x, y;
cin >> x >> y;
y = y + x - 1;
x = find(x, root), splay(x);
y = find(y + 2, root), splay(y);
if (f[x] != root) move(x);
rev_tag(rs(x));
updata(x), updata(y);
} void query_sum() {
int x, y;
cin >> x >> y;
y = y + x - 1;
x = find(x, root), splay(x);
y = find(y + 2, root), splay(y);
if (f[x] != root) move(x);
printf("%d\n", sum[rs(x)]);
} void query_max() {
printf("%d\n", Max[root]);
}
} splay; int main()
{
int n, m;
scanf("%d %d", &n, &m);
splay.init(n); // 先插入 n 个数并建立平衡树
while (n--)
{
string ss;
cin >> ss; if (ss[0] == 'I') { // 插入操作
splay.insert();
}
if (ss[0] == 'D') { // 删除操作
splay.Del();
}
if (ss[0] == 'M' && ss[2] == 'K') { // 修改操作
splay.cover();
}
if (ss[0] == 'R') { // 旋转操作
splay.reverse();
}
if (ss[0] == 'G') { // 求和操作
splay.query_sum();
}
if (ss[0] == 'M' && ss[2] == 'X') { // 修改操作
splay.query_max();
}
}
return 0;
}

题解 - 【NOI2015】维修数列的更多相关文章

  1. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

  2. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

  3. 【BZOJ】1500: [NOI2005]维修数列

    [算法]splay [题解]数据结构 感谢Occult的模板>_<:HYSBZ 1500 维修数列 #include<cstdio> #include<cctype> ...

  4. splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)

    先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...

  5. 【BZOJ-1500】维修数列 Splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11047  Solved: 3460[Submit][Statu ...

  6. [NOI2005] 维修数列

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 8397  Solved: 2530 Description In ...

  7. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

  8. [BZOJ1500][NOI2005]维修数列---解题报告

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  9. [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

    历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...

  10. BZOJ_1500_[NOI2005]维修数列_splay

    BZOJ_1500_[NOI2005]维修数列_splay 题意: 分析: 节点维护从左开始的最大连续子段和,从右开始的最大连续子段和,区间的最大连续子段和 插入:重新建一棵树,把pos旋到根,把po ...

随机推荐

  1. 虚拟机安装中标麒麟桌面版7.0系统 + 升级Firefox浏览器

    背景 由于公司业务(政府项目)需要走国产化路线,需要把原来已有的产品在国产的系统进行测试.目前选择的是中标麒麟系统,这是一款国产系统,界面 UI 和 window 类似,系统内核使用的是 Linux ...

  2. docker环境下的Grafana安装

    一.参考资源:https://grafana.com/docs/grafana/latest/installation/docker/ 二.过程 1.安装grafana 查看可用image [root ...

  3. CentOS 虚拟机 下载及 搭建

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) CentOS 虚拟机安装包下载 : 链接:https://pan.baidu.com/s/1JDIASm ...

  4. Linux (五) VIM编辑器

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.简介 ​ Linux系统环境下的一款非常重要的文本编辑工具,我们在Linux环境下几乎所有的文本文件 ...

  5. Java实现 LeetCode 718 最长重复子数组(动态规划)

    718. 最长重复子数组 给两个整数数组 A 和 B ,返回两个数组中公共的.长度最长的子数组的长度. 示例 1: 输入: A: [1,2,3,2,1] B: [3,2,1,4,7] 输出: 3 解释 ...

  6. Java实现 LeetCode 416 分割等和子集

    416. 分割等和子集 给定一个只包含正整数的非空数组.是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1: ...

  7. Java实现 LeetCode 297 二叉树的序列化与反序列化

    297. 二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得 ...

  8. Android如何使用SQLlite数据库

    先写一个类,继承自SQLiteOpenHelper public class MyDatabaseHelper extends SQLiteOpenHelper { //声明一个Context pri ...

  9. [OpenGL](翻译+补充)投影矩阵的推导

    1.简介 基本是翻译和补充 http://www.songho.ca/opengl/gl_projectionmatrix.html 计算机显示器是一个2D的平面,一个3D的场景要被OpenGL渲染必 ...

  10. Python 导入CSV、JSON、XML数据

    常见的机器可读格式包括: - 逗号分隔值(Comma-Separated Values,CSV)- 制表符分隔值(tab-separated values,TSV)- JavaScript 对象符号( ...