题面大意:

使用平衡树维护一个数列,支持插入,修改,删除,翻转,求和,求最大和这 \(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. LDA模型笔记

    “LDA(Latent Dirichlet Allocation)模型,模型主要解决文档处理领域的问题,比如文章主题分类.文章检测.相似度分析.文本分段和文档检索等问题.LDA主题模型是一个三层贝叶斯 ...

  2. Matlab矩阵学习三 矩阵的运算

    Matlab矩阵的运算 一.矩阵的加减 在matlab中,矩阵的加减和数的加减符号一样,都是"+"和”-“,不同的是两个进行运算的矩阵维度必须相同  二.数乘  三.乘法 矩阵乘法 ...

  3. .net core 上传大文件

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Thr ...

  4. Java实现 LeetCode 306 累加数

    306. 累加数 累加数是一个字符串,组成它的数字可以形成累加序列. 一个有效的累加序列必须至少包含 3 个数.除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和. 给定一个只包含数字 ...

  5. Javascript实现万年历(日历表)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. Java实现找零问题

    1 问题描述 现需找零金额为n,则最少需要用多少面值为d1 < d2 < d3 < - < dm的硬币?(PS:假设这m种面值d1 < d2 < d3 < - ...

  7. java实现圆周率

    我国古代数学家对圆周率方面的研究工作,成绩是突出的.三国时期的刘徽.南北朝时期的祖冲之都在这个领域取 得过辉煌战绩. 有了计算机,圆周率的计算变得十分容易了.如今,人们创造了上百种方法求π的值.其中比 ...

  8. Java实现第九届蓝桥杯书号验证

    书号验证 2004年起,国际ISBN中心出版了<13位国际标准书号指南>. 原有10位书号前加978作为商品分类标识:校验规则也改变. 校验位的加权算法与10位ISBN的算法不同,具体算法 ...

  9. Java实现第八届蓝桥杯最大公共子串

    最大公共子串 最大公共子串长度问题就是: 求两个串的所有子串中能够匹配上的最大长度是多少. 比如:"abcdkkk" 和 "baabcdadabc", 可以找到 ...

  10. 容器技术之Docker私有镜像仓库docker-distribution

    在前边的博客中我们说到docker的架构由docker客户端.服务端以及仓库组成:docker仓库就是用来存放镜像的地方:其实docker registry我们理解为存放docker镜像仓库的仓库比较 ...