题目链接:BZOJ - 1500

题目分析

我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= =

这道题是传说中的Splay维护数列的Boss题目。

前面的几个操作和询问看起来比较正常,就是最后一个维护最大区间和比较复杂。

其实这个也并不是十分复杂,只是要多维护一点东西,事实证明,我代码里的错误都不是与这个询问有关的。

维护每个节点的 Lmx[x] ,即这个节点的子树代表的区间的从左端开始的最大权值和。Rmx[x],同理。Mx[x],这个区间的最大权值和。

然而我的最大权值和都是可以为空的,也就是说如果只能取负数我就什么都不取,就是0。

题目规定的最大权值区间是不能为空的,所以我多维护了一个 Max[x],询问的时候判断如果 Max[x] < 0 ,就输出 Max[x],否则输出我维护的 Mx[x]。

............................然后就是我Debug了一天的东西.........................

经过一天悲剧的探索与尝试,我发现我的错误是出现在了Reverse操作有关的东西。

PushDown写得有非常严重的错误,下面来梳理一下正确的写法,以后要固定一下写法,不能一个代码一个写法...

首先,翻转一个区间的时候,假如这个区间子树的根节点是 x,就Reverse(x)。

之后,PushDown(x) 的时候,判断 Rev[x] 是否为 1,如果是1,就Reverse(Son[x][0]); Reverse(Son[x][1]);

注意,交换左右儿子的操作在Reverse(x)里完成。Rev[x]为1表示的是x的两个儿子还应被 Reverse,但是x的两个儿子的顺序已经是对的。是x的孙子的顺序需要被交换。

代码:

void Reverse(int x)
{Rev[x] ^= 1;swap(Son[x][0], Son[x][1]);
}        void PushDown(int x)
{if (Rev[x] == 0) return;if (Son[x][0]) Reverse(Son[x][0]);   if (Son[x][1]) Reverse(Son[x][1]);       Rev[x] = 0;
}

  

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>using namespace std;const int MaxN = 1000000 + 5, INF = 999999999;inline void Read(int &Num)
{char c = getchar();bool Neg = false;while (c < '0' || c > '9'){if (c == '-') Neg = true;c = getchar();}Num = c - '0'; c = getchar();while (c >= '0' && c <= '9'){Num = Num * 10 + c - '0';c = getchar();}if (Neg) Num = -Num;
}int n, m, Root, Index, Tot1, Tot2, Len;
int V[MaxN], A[MaxN], Father[MaxN], Son[MaxN][2], Sum[MaxN], Rev[MaxN], Stack[MaxN];
int Max[MaxN], Size[MaxN], Lmx[MaxN], Rmx[MaxN], Mx[MaxN], D[MaxN];bool Rep[MaxN];char Str[15];inline int gmax(int a, int b) {return a > b ? a : b;}
inline int gmin(int a, int b) {return a < b ? a : b;}inline void Update(int x)
{Size[x] = Size[Son[x][0]] + Size[Son[x][1]] + 1;Sum[x] = Sum[Son[x][0]] + Sum[Son[x][1]] + A[x];Max[x] = gmax(A[x], gmax(Max[Son[x][0]], Max[Son[x][1]]));Lmx[x] = gmax(Lmx[Son[x][0]], Sum[Son[x][0]] + A[x] + Lmx[Son[x][1]]);Rmx[x] = gmax(Rmx[Son[x][1]], Sum[Son[x][1]] + A[x] + Rmx[Son[x][0]]);Mx[x] = gmax(Rmx[Son[x][0]] + A[x] + Lmx[Son[x][1]], gmax(Rmx[x], Lmx[x]));Mx[x] = gmax(Mx[x], gmax(Mx[Son[x][0]], Mx[Son[x][1]]));
}inline void Replace(int x, int Num)
{Rep[x] = true;D[x] = Num;A[x] = Num;Sum[x] = Num * Size[x];Max[x] = Num; Lmx[x] = Rmx[x] = Mx[x] = gmax(0, Sum[x]);
}inline void Reverse(int x)
{Rev[x] ^= 1;swap(Son[x][0], Son[x][1]);swap(Lmx[x], Rmx[x]);
}inline void PushDown(int x)
{if (Rep[x]){if (Son[x][0]) Replace(Son[x][0], D[x]);if (Son[x][1]) Replace(Son[x][1], D[x]);Rep[x] = false;}if (Rev[x]) {if (Son[x][0]) Reverse(Son[x][0]);if (Son[x][1]) Reverse(Son[x][1]);Rev[x] = 0;}
}int NewNode(int a)
{int x;if (Tot2 > 0) x = Stack[Tot2--];else x = ++Tot1;Size[x] = 1;Son[x][0] = Son[x][1] = 0;Father[x] = 0;A[x] = Sum[x] = Max[x] = a;Lmx[x] = Rmx[x] = Mx[x] = gmax(a, 0);Rev[x] = 0; Rep[x] = false;return x;
}int Build(int s, int t)
{int x, m = (s + t) >> 1;x = NewNode(V[m]);if (s < m) {Son[x][0] = Build(s, m - 1);Father[Son[x][0]] = x;}if (t > m) {Son[x][1] = Build(m + 1, t);Father[Son[x][1]] = x;}Update(x);return x;
}void Rotate(int x, int f)
{int y = Father[x];if (y == 0) return;Son[y][f ^ 1] = Son[x][f];if (Son[x][f]) Father[Son[x][f]] = y;Father[x] = Father[y];if (Father[y]) {if (y == Son[Father[y]][0]) Son[Father[y]][0] = x;else Son[Father[y]][1] = x;}Son[x][f] = y;Father[y] = x;Update(y);Update(x);
}void Splay(int x, int d)
{if (x == d) return;int y;while (Father[x] != d) {y = Father[x];if (Father[y] == d) {if (x == Son[y][0]) Rotate(x, 1);else Rotate(x, 0);break;          }if (y == Son[Father[y]][0]) {if (x == Son[y][0]){Rotate(y, 1);Rotate(x, 1);}else{Rotate(x, 0);Rotate(x, 1);}}else{if (x == Son[y][1]){Rotate(y, 0);Rotate(x, 0);}else{Rotate(x, 1);Rotate(x, 0);}}}if (Father[x] == 0) Root = x;
}int Find(int Num)
{int x = Root, k = Num;PushDown(x);while (Size[Son[x][0]] + 1 != k){if (Size[Son[x][0]] + 1 > k){x = Son[x][0];}else{k -= Size[Son[x][0]] + 1;x = Son[x][1];}PushDown(x);}return x;
}void Delete(int x)
{if (x == 0) return;if (Son[x][0]) Delete(Son[x][0]);if (Son[x][1]) Delete(Son[x][1]);Stack[++Tot2] = x;
}int main()
{scanf("%d%d", &n, &m);Tot1 = Tot2 = 0;Len = n;for (int i = 1; i <= n; ++i) Read(V[i]);Max[0] = -INF;int Temp;Root = Build(1, n);Splay(Find(1), 0);Temp = NewNode(-INF);Son[Root][0] = Temp;Father[Temp] = Root;Update(Root);Splay(Find(n + 1), 0);Temp = NewNode(-INF);Son[Root][1] = Temp;Father[Temp] = Root;Update(Root);int Pos, Tot, New, Num, x, y;for (int i = 1; i <= m; ++i) {scanf("%s", Str);if (strcmp(Str, "INSERT") == 0) {Read(Pos); Read(Tot);Len += Tot;for (int j = 1; j <= Tot; ++j) scanf("%d", &V[j]);New = Build(1, Tot);x = Find(Pos + 1);y = Find(Pos + 2);Splay(x, 0);Splay(y, x);Son[y][0] = New;Father[New] = y;Update(y);Update(x);}else if (strcmp(Str, "DELETE") == 0){Read(Pos); Read(Tot);Len -= Tot;x = Find(Pos);y = Find(Pos + Tot + 1);Splay(x, 0);Splay(y, x);Delete(Son[y][0]);Son[y][0] = 0;Update(y);Update(x);}else if (strcmp(Str, "MAKE-SAME") == 0){Read(Pos); Read(Tot); Read(Num);x = Find(Pos);y = Find(Pos + Tot + 1);Splay(x, 0);Splay(y, x);Replace(Son[y][0], Num);Update(y);Update(x);}else if (strcmp(Str, "REVERSE") == 0){Read(Pos); Read(Tot);x = Find(Pos);y = Find(Pos + Tot + 1);Splay(x, 0);Splay(y, x);Reverse(Son[y][0]);Update(y);Update(x);}else if (strcmp(Str, "GET-SUM") == 0){Read(Pos); Read(Tot);x = Find(Pos);y = Find(Pos + Tot + 1);Splay(x, 0);Splay(y, x);printf("%d\n", Sum[Son[y][0]]);}else if (strcmp(Str, "MAX-SUM") == 0){x = Find(1);y = Find(Len + 2);Splay(x, 0);Splay(y, x);if (Max[Son[y][0]] <= 0) printf("%d\n", Max[Son[y][0]]);else printf("%d\n", Mx[Son[y][0]]);}}return 0;
}

  

转载于:https://www.cnblogs.com/JoeFan/p/4336035.html

[BZOJ 1500] [NOI2005] 维修数列相关推荐

  1. 1500: [NOI2005]维修数列 (Splay)

    1W1A(inf开太大) #include<algorithm> #include<iostream> #include<cstring> #include< ...

  2. [BZOJ1500][NOI2005]维修数列(splay)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 16266  Solved: 5410 [Submit][Sta ...

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

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

  4. 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)

    因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...

  5. BZOJ1500 [NOI2005]维修数列(Splay tree)

    [Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线' _ '表示实际输入文件中的空格 Inp ...

  6. bzoj1500: [NOI2005]维修数列

    模板题 之前还写了点铺垫题 bzoj3223 教你如何reverse bzoj1507 教你如何维护序列 bzoj1269 教你如何维护序列&reverse 然后再做这个题就好多啦 #incl ...

  7. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay) 手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.ne ...

  8. 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

    339. [NOI2005] 维护数列 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线' _ '表示实际 ...

  9. BZOJ 1500 维修数列

    Splay序列操作的大模板题 这个真的是噩梦..调了整整一个晚上,可以说完全被榨干了orz.. 因为我的splay写的实在是太丑了,手动加的哨兵节点,开头忘记pushup了,找了一晚上才找到... 还 ...

最新文章

  1. 4.5 人脸验证与二分类-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
  2. lazada发货_Lazada怎么发货?最全Lazada发货流程及注意事项!值得收藏!
  3. rufus中gpt和mrb磁盘_计算机关于磁盘的大杂烩
  4. python使用技巧_python小技巧
  5. python中pickle模块_python标准库学习之pickle模块
  6. 【图像去噪】基于matlab中值+均值+Lee+Kuan图像滤波【含Matlab源码 1179期】
  7. chrome 下载东西 失败禁止_用谷歌浏览器为什么没法下载文件?
  8. 六级,我一定要考好!
  9. 9N90-ASEMI大功率场效应管9A 900V
  10. java pv uv_什么是pv和uv?
  11. 数据库实验六---存储过程
  12. 无人机相关的基本术语小结
  13. 使用Python将文件名中的汉字序号改为阿拉伯数字序号
  14. MATLAB在线工具,画图啥的都不用安装了,超级实用
  15. 神经网络基础知识第一章
  16. cf计算机中丢失MSVCP100.dll,求助。电脑都要把我气死了。帮老弟瞅瞅
  17. SpringBoot使用Undertow做服务器
  18. java使用Jacob笔记
  19. 【字节2019春招】万万没有想到之聪明的编辑
  20. 15GB的电影压缩到64KB

热门文章

  1. Hadoop服务器集群安装部署及配置
  2. 【客户下单】后台提供webservice服务接收数据
  3. Java二维数组排序(按照某一列值大小)
  4. 定义,公理,定理,引理,推论,命题,推测,猜想
  5. java逆数组如何print_Java 逆数组
  6. mysql 测试快生产慢_生产上MySQL慢查询优化实战,SQL优化实战
  7. python3连接sql server数据库_Python3操作SQL Server数据库(实例讲解)
  8. 《剑指offer》——04. 二维数组中的查找——暴力法、线性查找——java实现
  9. npoi 所有列调整为一页_必能用到,一页PPT中想放超多图片怎么办?
  10. VS2010 断点无法命中的解决方案