题目链接: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. IOS 整理

    防止程序进入休眠状态 设置应用程序的 idleTimerDisabled 属性为 YES (默认为NO) [UIApplication sharedApplication].idleTimerDisa ...

  2. GUI编程笔记(java)04:GUI(HelloWorld)窗体案例

    1.Frame 在JAVA中,Frame是一种控件,可作为父窗体加载其他swing控件.案例: package cn.itcast_01; import java.awt.Frame; public ...

  3. SELECT [Code] ,[AlarmID] ,[ItemName] ,[isDeleted] ,[Remark] FROM [LjlData].[dbo].[T_BaseDetail] union select 0--

    SELECT  [id]       ,[AlarmID]       ,[ItemName]       ,[isDeleted]       ,[Remark]   FROM [LjlData]. ...

  4. 还原或删除sql server 2008数据库时,经常烩出现: “因为数据库正在使用,所以无法获得对数据库的独占访问权”,终解决方案

    还原或删除sql server 2008数据库时,经常烩出现: “因为数据库正在使用,所以无法获得对数据库的独占访问权”,终解决方案如下 关键SQL语句: ALTER DATABASE [dateba ...

  5. python基础知识五

    数据结构基本上就是---它们可以处理一些数据的结构.或者说,它们是用来存储一组相关数据的. python中有三种内建的数据结构---列表.元祖和字典. 我们将会学习如何使用它们,以及它们如何使编程变得 ...

  6. Android30-Fragment-理解

        Android30-Fragment-理解 规范 mobileSafe V2.0 欢迎页面 用户第一次是否需要用户提示 新闻类app的数据是怎么获取的 知乎提问?如何把身边资源最大化 第二种就 ...

  7. For each db / table

    use master go exec master..sp_MSforeachdb 'use [?]; IF (SELECT db_id(''?'')) > 4 and (SELECT DATA ...

  8. 【FJOI2014】【偏导+数学】病毒防护带

    转载:http://trinklee.blog.163.com/blog/static/23815806020150155296528/ 问题描述: 众所周知,在国王胖哥的带领下,K国国泰民安,空前繁 ...

  9. Windows Phone 之播放视频

    在Windows Phone 7中播放视频有两种方式, (1)使用MediaElement 控件来播放:用MediaElement 控件来播放视频比较灵活,你需要自己去实现播放暂停进度条等等的功能,播 ...

  10. 自定义流程gooflow.08 demo在线演示

    一.功能简介 gooflow功能清单1.自定义流程绘制2.自定义属性添加3.支持3种步骤类型 普通审批步骤 自动决策步骤 手动决策步骤 4.决策方式(支持js决策,sql语句决策) 5.审批人员参与方 ...