描述

要求支持区间插入、区间修改、区间翻转、区间删除、区间求和 和求和最大的子列.

分析

  • 从最开始学完splay做了翻转区间后就想做这个题目, 结果WA了N次后失去调试的信心, 40分收场(这题暴力30分)
  • 快省选了想拿出来再做一下, 因为splay的区间操作这个题算是最全的了, 不做一下的话总担心模版是错的.
  • 然后做了好长时间...终于不耐烦了拿HZWER的改了改, 直到改到所有操作和我的都写的一模一样——除了标记下传. 然后就很开(伤)心地接受了这个现实.
  • 在网上看每个人写的标记下传都不一样, 有的写的简单有的很复杂(比如HZWER). 但一种标记下传对应一种维护方式吧, 看网上很少有写如何处理细节的, 我就写详细点吧.
  • 首先, mls, mrs, maxs分别记录左、右端开始的最大子序列和, 和整段区间的最大子序列和.
  • 规定如果整段区间为负值, mls和mrs可以取0, 而maxs必须取一个存在的数, 这样也是为了维护起来方便吧.
  • 那么mls可以取左子结点的mls、左子结点的sum+根结点的权值+右子结点的mls. mrs同理.
  • maxs可以取左子结点的maxs、右子结点的maxs、左子结点的mrs+根结点权值+右子结点的mls.
  • 这就是mls、mrs最小为0的优势.
  • 在标记下传时下传的实际上是子结点的标记, 而根结点的标记实际上已经在此之前生效了. 这样可以避免在旋转时出错. 旋转里的那个 ch[p][d] 的标记可能没有生效.
  • 遇到带区间修改的题目都要用这种标记下传的方式吧..
  • 又想起原来写过的区间翻转类的题目, 那里的标记下传只需要下传当前节点的即可, 那是因为翻转不影响最大值、不影响求和. 而区间修改会影响.
#include #include using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 3000000;
int n, m;
int fa[maxn], ch[maxn][2], id[maxn];
int mls[maxn], mrs[maxn], maxs[maxn], s[maxn], rech[maxn], v[maxn], sumv[maxn];
bool mdf[maxn], rev[maxn];
#define lc ch[o][0]
#define rc ch[o][1]
void update(int o) {
s[o] = s[lc] + s[rc] + 1;
sumv[o] = sumv[lc] + sumv[rc] + v[o];
maxs[o] = max(maxs[lc], maxs[rc]);
maxs[o] = max(maxs[o], mrs[lc] + v[o] + mls[rc]);
mls[o] = max(mls[lc], sumv[lc] + v[o] + mls[rc]);
mrs[o] = max(mrs[rc], sumv[rc] + v[o] + mrs[lc]);
}
void pushdown(int o) {
if(mdf[o]) {
mdf[o] = rev[o] = 0;
if(lc) mdf[lc] = 1, v[lc] = v[o], sumv[lc] = v[o]*s[lc];
if(rc) mdf[rc] = 1, v[rc] = v[o], sumv[rc] = v[o]*s[rc];
if(v[o] >= 0) {
if(lc) mls[lc] = mrs[lc] = maxs[lc] = sumv[lc];
if(rc) mls[rc] = mrs[rc] = maxs[rc] = sumv[rc];
} else {
if(lc) mls[lc] = mrs[lc] = 0, maxs[lc] = v[o];
if(rc) mls[rc] = mrs[rc] = 0, maxs[rc] = v[o];
}
}
if(rev[o]) {
rev[o]^=1;
rev[lc]^=1;
rev[rc]^=1;
swap(mls[lc], mrs[lc]);
swap(mls[rc], mrs[rc]);
swap(ch[lc][0], ch[lc][1]);
swap(ch[rc][0], ch[rc][1]);
}
}
void rotate(int& o, int x)  {
int p = fa[x], q = fa[p];
bool d = (ch[p][1] == x), d2 = (ch[q][1] == p);
if(o == p) o = x; else ch[q][d2] = x;
fa[x] = q; fa[p] = x; fa[ch[p][d] = ch[x][d^1]] = p;
ch[x][d^1] = p; update(p); update(x);
}
void splay(int& o, int x) {
while(o != x) {
int p = fa[x], q = fa[p];
if(o != p)
if(ch[p][0] == x^ch[q][0] == p) rotate(o, x);
else rotate(o, p);
rotate(o, x);
}
}
void build(int L, int R, int p, int d) {
if(L > R) return;
int o = (L+R)>>1;
ch[p][d] = o; fa[o] = p;
build(L, o-1, o, 0);
build(o+1, R, o, 1);
update(o);
}
int kth(int o, int k) {
pushdown(o);
if(s[lc] + 1 == k) return o;
else if(s[lc] >= k) return kth(lc, k);
else return kth(rc, k-s[lc]-1);
}
int o, pos, tot, val;
void insert() {
splay(o, kth(o, pos+1));
splay(rc, kth(o, pos+2));
for(int i = n+1; i <= n+tot; i++) scanf("%d", &v[i]);
build(n+1, n+tot, rc, 0);
n += tot; //
update(rc); update(o);
}
void remove() {
splay(o, kth(o, pos));
splay(rc, kth(o, pos + tot + 1));
ch[rc][0] = 0;
update(rc); update(o);
}
void modify() {
splay(o, kth(o, pos));
splay(rc, kth(o, pos + tot + 1));
int p = ch[rc][0];
v[p] = val;
mdf[p] = 1;
sumv[p] = v[p]*s[p];
if(val >= 0) mls[p] = mrs[p] = maxs[p] = sumv[p];
else mls[p] = mrs[p] = 0, maxs[p] = v[p];
update(rc); update(o);
}
void rever() {
splay(o, kth(o, pos));
splay(rc, kth(o, pos + tot + 1));
if(!mdf[o]) {
int p = ch[rc][0];
rev[p]^=1;
swap(ch[p][0], ch[p][1]);
swap(mls[p], mrs[p]);
}
update(rc); update(o);
}
void query() {
splay(o, kth(o, pos));
splay(rc, kth(o, pos + tot + 1));
printf("%d\n", sumv[ch[rc][0]]);
}
int main()
{
scanf("%d %d", &n, &m); n += 2;
v[1] = v[n] = maxs[0] = -INF; //
for(int i = 2; i < n; i++) scanf("%d", &v[i]);
build(1, n, 0, 0);
o = (n+1)>>1;
for(int i = 1; i <= m; i++) {
char opt[10];
scanf("%s", opt);
switch(opt[2]) {
case 'S': scanf("%d %d", &pos, &tot); insert(); break;
case 'L': scanf("%d %d", &pos, &tot); remove(); break;
case 'V': scanf("%d %d", &pos, &tot); rever(); break;
case 'T': scanf("%d %d", &pos, &tot); query(); break;
case 'K': scanf("%d %d %d", &pos, &tot, &val); modify(); break;
case 'X': printf("%d\n", maxs[o]);
}
}
return 0;
}
#include #include using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 3000000;
int n, m;
int ch[maxn][2], id[maxn];
int mls[maxn], mrs[maxn], maxs[maxn], s[maxn], rech[maxn], v[maxn], sumv[maxn];
bool mdf[maxn], rev[maxn];
#define lc ch[o][0]
#define rc ch[o][1]
void update(int o) {
s[o] = s[lc] + s[rc] + 1;
sumv[o] = sumv[lc] + sumv[rc] + v[o];
maxs[o] = max(maxs[lc], maxs[rc]);
maxs[o] = max(maxs[o], mrs[lc] + v[o] + mls[rc]);
mls[o] = max(mls[lc], sumv[lc] + v[o] + mls[rc]);
mrs[o] = max(mrs[rc], sumv[rc] + v[o] + mrs[lc]);
}
void pushdown(int o) {
if(mdf[o]) {
mdf[o] = rev[o] = 0;
if(lc) mdf[lc] = 1, v[lc] = v[o], sumv[lc] = v[o]*s[lc];
if(rc) mdf[rc] = 1, v[rc] = v[o], sumv[rc] = v[o]*s[rc];
if(v[o] >= 0) {
if(lc) mls[lc] = mrs[lc] = maxs[lc] = sumv[lc];
if(rc) mls[rc] = mrs[rc] = maxs[rc] = sumv[rc];
} else {
if(lc) mls[lc] = mrs[lc] = 0, maxs[lc] = v[o];
if(rc) mls[rc] = mrs[rc] = 0, maxs[rc] = v[o];
}
}
if(rev[o]) {
rev[o]^=1;
rev[lc]^=1;
rev[rc]^=1;
swap(mls[lc], mrs[lc]);
swap(mls[rc], mrs[rc]);
swap(ch[lc][0], ch[lc][1]);
swap(ch[rc][0], ch[rc][1]);
}
}
void rotate(int& o, int d) {
int p = ch[o][d^1]; ch[o][d^1] = ch[p][d]; ch[p][d] = o;
update(o); update(p); o = p;
}
int cmp(int o, int k) {
if(s[lc] + 1 == k) return -1;
return k < s[lc] + 1 ? 0 : 1;
}
void splay(int& o, int k) {
pushdown(o);
int d = cmp(o, k);
if(d == -1) return;
if(d == 1) k -= (s[lc] + 1);
int p = ch[o][d];
pushdown(p);
int d2 = cmp(p, k);
int k2 = (d2 == 0 ? k : k-s[ch[p][0]]-1);
if(d2 != -1) {
splay(ch[p][d2], k2);
if(d == d2) rotate(o, d^1); else rotate(ch[o][d], d);
}
rotate(o, d^1);
}
void build(int& o, int L, int R) {
if(L > R) return;
o = (L+R)>>1;
build(lc, L, o-1);
build(rc, o+1, R);
update(o);
}
void getInterval(int& o, int pos, int tot) {
splay(o, pos);
splay(rc, pos + tot - s[lc]);
}
int o, pos, tot, val;
void insert() {
getInterval(o, pos+1, 0);
for(int i = n+1; i <= n+tot; i++) scanf("%d", &v[i]);
build(ch[rc][0], n+1, n+tot);
n += tot; //
update(rc); update(o);
}
void remove() {
getInterval(o, pos, tot);
ch[rc][0] = 0;
update(rc); update(o);
}
void modify() {
getInterval(o, pos, tot);
int p = ch[rc][0];
v[p] = val;
mdf[p] = 1;
sumv[p] = v[p]*s[p];
if(val >= 0) mls[p] = mrs[p] = maxs[p] = sumv[p];
else mls[p] = mrs[p] = 0, maxs[p] = v[p];
update(rc); update(o);
}
void rever() {
getInterval(o, pos, tot);
if(!mdf[o]) {
int p = ch[rc][0];
rev[p]^=1;
swap(ch[p][0], ch[p][1]);
swap(mls[p], mrs[p]);
}
update(rc); update(o);
}
void query() {
getInterval(o, pos, tot);
printf("%d\n", sumv[ch[rc][0]]);
}
int main()
{
scanf("%d %d", &n, &m); n += 2;
v[1] = v[n] = maxs[0] = -INF; //
for(int i = 2; i < n; i++) scanf("%d", &v[i]);
build(o, 1, n);
for(int i = 1; i <= m; i++) {
char opt[10];
scanf("%s", opt);
switch(opt[2]) {
case 'S': scanf("%d %d", &pos, &tot); insert(); break;
case 'L': scanf("%d %d", &pos, &tot); remove(); break;
case 'V': scanf("%d %d", &pos, &tot); rever(); break;
case 'T': scanf("%d %d", &pos, &tot); query(); break;
case 'K': scanf("%d %d %d", &pos, &tot, &val); modify(); break;
case 'X': printf("%d\n", maxs[o]);
}
}
return 0;
}

CODEVS-1758-维护数列-NOI2005-splay相关推荐

  1. [bzoj1500 维修数列](NOI2005) (splay)

    真的是太弱了TAT...光是把代码码出来就花了3h..还调了快1h才弄完T_T 号称考你会不会splay(当然通过条件是1h内AC..吓傻)... 黄学长的题解:http://hzwer.com/28 ...

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

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

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

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

  4. [NOI2005]维护数列 恶心到毁天灭地的splay

    传送门 debug到死2333. 虽然说是splay维护序列模板,作为蒟蒻的我还是GG %%%考场A的dalao Orz  Orz. 其实不开long long也行,inf开成0x3f3f3f3f也可 ...

  5. [NOI2005]维护数列

    输入格式 输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目. 第 2 行包含 N 个数字,描述初始时的数列. 以下 M 行,每行一条命令,格式参见问题 ...

  6. JZOJ 2413. 【NOI2005】维护数列

    Description 请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线' _ '表示实际输入文件中的空格) 1. 插入 INSERT_posi_tot_c1_c2_-_c ...

  7. [luogu2042] [NOI2005]维护数列

    前言 写写比较麻烦的这题 题目相关 题目大意 写一个大数据结构 数据范围 20000 题目链接 前置 先过模板题,比如会个非旋treap,写一下,通过[luogu3369][模板]普通平衡树 poss ...

  8. YBTOJ洛谷P2042:维护数列(平衡树)

    文章目录 题目描述 解析 删除区间 插入数列 修改&翻转 区间和&最大子段和 代码 传送门 题目描述 解析 阴间题- 这不是裸的板子吗? 国赛真的有人能把这题写出来吗- 应该算一道练习 ...

  9. [CODEVS 1281] Xn数列

    描述 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn http://codevs.cn/problem/1281/ 分析 比较裸的矩阵乘法题, ...

  10. 伸展树(Splay tree)图解与实现

    伸展树(Splay tree)图解与实现 伸展树(Splay tree)图解与实现_小张的专栏-CSDN博客_splay树 Splay树详解 Splay树详解 - 秦淮岸灯火阑珊 - 博客园 平衡树 ...

最新文章

  1. 判断是否为闰年oracle,ORACLE 通过日期变量判断是否闰年
  2. [20160321]bvi使用问题2.txt
  3. 分布式消息队列 — RabbitMQ(1)
  4. mysql 配置文件设置最大链接数 max_connections不生效
  5. 华为交换机配置Telnet
  6. netty系列之:对聊天进行加密
  7. centos6.5和centos7.5统一字符集为zh_CN.UTF-8解决系统和MySQL数据库乱码问题
  8. mysql 学习笔记 11过程控制
  9. 2021当代青年婚恋状态研究报告
  10. iOS学习笔记15-设计模式之 适配器模式
  11. 模板字符串竟然还有这种用法
  12. Xmind 2022中文高效学习思维导图
  13. catia 桥接曲面圆角_CATIA建模教程(二)——圆角及桥接在空间曲线中的应用.pdf...
  14. 华为S5700交换机端口聚合
  15. 解决hotmail邮箱无法登陆问题
  16. NoMachine出现 The session negotiation failed的解决方案及踩坑总结
  17. 软件项目管理 3.5.敏捷生存期模型
  18. 项目管理软件售后培训方案
  19. html5 video js控制摄像头的焦距,H5中使用video标签实现选择摄像头功能的示例
  20. Django入门超easy系列(一)——— 从一个简单的例子入门

热门文章

  1. 科大星云诗社动态20210508
  2. [云炬python3玩转机器学习笔记] 2-6关于回归和分类
  3. 手撕 CNN 经典网络之 VGGNet(理论篇)
  4. 无盘服务器怎么修改ip,怎么进入无盘服务器修改IP地址呢
  5. “sql2005管道的另一端上无任何进程”及附带一系列问题完整解决方法
  6. 实验七 寻址方式在结构化数据访问中的应用
  7. phonegap在android中如何退出程序
  8. 用OpenJTAG烧写程序到Flash—— 韦东山嵌入式Linux视频学习笔记03
  9. 「 每日一练,快乐水题 」717. 1比特与2比特字符
  10. JVM_03 运行时数据区 [ 虚拟机栈 ]