题目链接: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;
}

  

[BZOJ 1500] [NOI2005] 维修数列的更多相关文章

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

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

  2. BZOJ 1500: [NOI2005]维修数列 (splay tree)

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

  3. BZOJ 1500 [NOI2005]维修数列 FHQ Treap

    终于A了这题...这题还是很好...但是我太菜...重构了三遍qwq FHQ Treap大法好!qwq...~~ Ins:直接拿输入造一棵树,把原来的树split成[1,pos],[pos+1,n], ...

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

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

  5. 【BZOJ】1500: [NOI2005]维修数列(splay+变态题)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 模板不打熟你确定考场上调试得出来? 首先有非常多的坑点...我遇到的第一个就是,如何pushu ...

  6. 1500: [NOI2005]维修数列

    Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...

  7. bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...

  8. [NOI2005] 维修数列

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

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

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

随机推荐

  1. .h头文件 .lib库文件 .dll动态库文件之间的关系

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的. 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和lib就够 ...

  2. DTrace to Troubleshoot Java Native Memory Problems

    How to Use DTrace to Troubleshoot Java Native Memory Problems on Oracle Solaris 11 Hands-On Labs of ...

  3. 传输层:TCP UDP SCTP

    总图 虽然协议族被称为“TCP/IP”,但除了TCP和IP这两个主要协议外,还有许多其他成员.图2-1展示了这些协议的概况. 图2-1中同时展示了IPV4和IPV6.从右向左看该图,最右边的5个网络应 ...

  4. hibernate入门之person表

    下面的hibernate入门person表指的是:根据mysql数据库中的test表和其中的元素-->建立映射表==>进而创建持久化类的顺序来操作了,下面为步骤 1.配置MySQL驱动程序 ...

  5. 所有Mac用户都需要知道的9个实用终端命令行<转>

    转自 http://www.macx.cn/thread-2075903-1-1.html 通常情况下,只有高端用户才会经常用到终端应用.这并不意味着命令行非常难学,有的时候命令行可以轻松.快速的解决 ...

  6. Java SE (1)之 JFrame 组件 GridLayout布局

    package com.sunzhiyan; import java.awt.*; import javax.swing.*; public class Demo_2 extends JFrame{ ...

  7. 单点登录SSO原理

    最近接触了一点单点登录的知识,有一点理解,记录一下.有些问题并没有找到完美的解决方法,还需要找点已有框架来看看. 欢迎留言探讨. 1       概念 1.1     概念及理解 有一个网上广为流传的 ...

  8. WisDom.Net 框架设计(四) 用户安全

    WisDom.Net  ----用户安全 1.用户单机登录 正如其名这里要求其实就是显示用户只能在一台电脑上登录.防止多处登录,这里简单的说一下实现原理,我们在这里使用session +cookie ...

  9. 使用LuaInterface遇到的编码问题

    今天使用LuaInterface加载脚本时忽然报“未知字符”错误信息!于是检查文件编码 将其修改为“US ASCII” 就好了.

  10. Animating Layout Changes(展开收起)

    原文地址:https://developer.android.com/training/animation/layout.html#add (1)设置布局文件: <LinearLayout an ...