题目大意

给出一个由N个整数组成的序列A,你需要应用M个操作:

I p x 在p 处插入一个元素 x (解释:这里插入是p - 1和p 之间插入)
D p   删除p 处的一个元素
R p x 修改p 处元素的值为 x
Q l r 查询一个区间[l,r]的最大子段和

N <= 100000, M <= 100000

主要思路:FHQ Treap 维护区间

同学们应该都做过GSS系列其他的一些题目,所以维护最大子段和的具体套路这里就不详讲了。真的不懂的话看这里的后半篇

我的代码中套用了与楼下GKxx大佬的update方式,也就是习惯性的分情况讨论。

然后就是FHQ Treap维护区间的问题了。(这里默认大家会FHQ Treap的维护数据的写法,如果是Splay党的话,推荐GKxx大佬的题解)

我们在维护数据时,split是按照值的大小来分的:

inline void split(int rt, int k, int &x, int &y) {if(!rt) x = y = 0;else {if(k > z[rt].w) {y = rt, split(z[rt].ch[0], k, x, z[rt].ch[0]);} else {x = rt, split(z[rt].ch[1], k, z[rt].ch[1], y);}update(rt);}
}

但是对于一个区间,我们总不能在哪个位置就把另外设的一个权值标上位置吧,这样插入时会有一定的错误。

这时我们可以采用类似findkth的方法split,也就是按照这个点的size值来找第几个。如:

inline void split(int rt, int k, int &x, int &y) {if(!rt) x = y = 0;else {if(k <= z[z[rt].ch[0]].sze) {// k与左儿子的size比较y = rt, split(z[rt].ch[0], k, x, z[rt].ch[0]);} else {x = rt, split(z[rt].ch[1], k - z[z[rt].ch[0]].sze - 1, z[rt].ch[1], y);// 这里有个细节:右子树的size一定记得把k先减去左子树的size和这个节点(-1)}update(rt);}
}

然后其他的就没有别的什么特别的了。在提取区间时只需要split一下r,然后split一下l - 1,分成的三棵子树中中间的那棵子树就是维护l ~ r的节点了。

记得开大点数组!!!否则WA的你天崩地裂(经验之谈)

(我开了大约400000才过,反正200000是过不了的,不太清楚为什么)

还有,记得开long long才行,因为数据范围(逃

code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <ctime>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define mn 400010
#define inf 1 << 30
#define ll long long
inline int read() {int x = 0, f = 1; char ch = getchar();while(ch > '9' || ch < '0') { if(ch == '-') f = -f; ch = getchar(); }while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }return x * f;
}
struct tree{int pri, ch[2], sze;ll x, sum, lsum, rsum, msum;
} z[mn];
inline void update(int rt)
{z[rt].sum = z[rt].x, z[rt].sze = 1;if (z[rt].ch[0])z[rt].sum += z[z[rt].ch[0]].sum, z[rt].sze += z[z[rt].ch[0]].sze;if (z[rt].ch[1])z[rt].sum += z[z[rt].ch[1]].sum, z[rt].sze += z[z[rt].ch[1]].sze;if (z[rt].ch[0] && z[rt].ch[1]) {z[rt].lsum = max(z[z[rt].ch[0]].lsum, z[z[rt].ch[0]].sum + z[rt].x + z[z[rt].ch[1]].lsum);z[rt].rsum = max(z[z[rt].ch[1]].rsum, z[z[rt].ch[1]].sum + z[rt].x + z[z[rt].ch[0]].rsum);z[rt].msum = max(max(z[z[rt].ch[0]].msum, z[z[rt].ch[1]].msum), z[z[rt].ch[0]].rsum + z[z[rt].ch[1]].lsum + z[rt].x);} else if (z[rt].ch[0]) {z[rt].lsum = max(max(z[z[rt].ch[0]].lsum, z[z[rt].ch[0]].sum + z[rt].x), 0ll);z[rt].rsum = max(z[z[rt].ch[0]].rsum + z[rt].x, 0ll);z[rt].msum = max(z[z[rt].ch[0]].msum, z[z[rt].ch[0]].rsum + z[rt].x);} else if (z[rt].ch[1]) {z[rt].lsum = max(z[z[rt].ch[1]].lsum + z[rt].x, 0ll);z[rt].rsum = max(max(z[z[rt].ch[1]].rsum, z[z[rt].ch[1]].sum + z[rt].x), 0ll);z[rt].msum = max(z[z[rt].ch[1]].msum, z[z[rt].ch[1]].lsum + z[rt].x);} else {z[rt].lsum = z[rt].rsum = max(z[rt].x, 0ll);z[rt].msum = z[rt].x;}
}
int cnt;
inline int newnode(int v = 0) {z[++cnt].x = z[cnt].msum = z[cnt].sum = v;z[cnt].lsum = z[cnt].rsum = max(v, 0);z[cnt].sze = 1;z[cnt].pri = rand();return cnt;
}
inline int merge(int x, int y) {if(!x || !y) return x + y;if(z[x].pri < z[y].pri) {z[x].ch[1] = merge(z[x].ch[1], y);update(x);return x;} else {z[y].ch[0] = merge(x, z[y].ch[0]);update(y);return y;}
}
inline void split(int rt, int k, int &x, int &y) {if(!rt) x = y = 0;else {if(k <= z[z[rt].ch[0]].sze) {y = rt, split(z[rt].ch[0], k, x, z[rt].ch[0]);} else {x = rt, split(z[rt].ch[1], k - z[z[rt].ch[0]].sze - 1, z[rt].ch[1], y);}update(rt);}
}
int n, m, xx, yy, zz, rot;
inline void debug() {go(rt, 1, cnt, 1) {printf("%d: pri:%d, sze:%d, ch[0]:%d, ch[1]:%d, x:%d\n", rt, z[rt].pri, z[rt].sze, z[rt].ch[0], z[rt].ch[1], z[rt].x);}printf("\n");
}
int main() {srand((unsigned)time(NULL));n = read();go(i, 1, n, 1) {int x = read();split(rot, i, xx, yy);rot = merge(merge(xx, newnode(x)), yy);} m = read();go(i, 1, m, 1) {char s;cin >> s;int x = read(), v;if(s == 'I') {v = read();split(rot, x - 1, xx, yy);  rot = merge(merge(xx, newnode(v)), yy);} else if(s == 'D') {split(rot, x, xx, zz);split(xx, x - 1, xx, yy);yy = merge(z[yy].ch[0], z[yy].ch[1]);rot = merge(merge(xx, yy), zz);} else if(s == 'R') {v = read();split(rot, x, xx, zz);split(xx, x - 1, xx, yy);z[yy].x = v;z[yy].sum = z[yy].msum = v;z[yy].lsum = z[yy].rsum = max(v, 0);rot = merge(merge(xx, yy), zz);} else if(s == 'Q') {v = read();split(rot, v, xx, zz);split(xx, x - 1, xx, yy);printf("%lld\n", z[yy].msum);rot = merge(merge(xx, yy), zz);}}return 0;
}

希望可以帮到WA了半天数组开小或者没开long long的同学

(我可是因为这两个调了一天啊QAQ)

转载于:https://www.cnblogs.com/yizimi/p/10056341.html

题解 SP4487 【GSS6 - Can you answer these queries VI】相关推荐

  1. SPOJ 4487 Can you answer these queries VI

    SPOJ_4487 其实这个题目和GSS1是差不多的,只不过由于有增加和删除的操作,这样用线段树就搞不定了,因此可以维护一个splay来实现这些操作. 但是一开始我写出的程序总是TLE,而和网上一些A ...

  2. SPOJ 4487. Can you answer these queries VI splay

    题目链接:点击打开链接 题意比較明显,不赘述. 删除时能够把i-1转到根,把i+1转到根下 则i点就在 根右子树 的左子树,且仅仅有i这一个 点 #include<stdio.h> #in ...

  3. HDU 1027 G - Can you answer these queries?

    http://acm.hdu.edu.cn/showproblem.php?pid=4027 Can you answer these queries? Time Limit: 4000/2000 M ...

  4. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  5. 线性代数四之动态DP(广义矩阵加速)——Can you answer these queries III,保卫王国

    动态DP--广义矩阵加速 SP1716 GSS3 - Can you answer these queries III description solution code [NOIP2018 提高组] ...

  6. SPOJ GSS2 Can you answer these queries II (线段树离线) - xgtao -

    Can you answer these queries II 这是一道线段树的题目,维护历史版本,给出N(<=100000)个数字(-100000<=x<=100000),要求求出 ...

  7. HDU 4027 Can you answer these queries?(线段树/区间不等更新)

    传送门 Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/6576 ...

  8. GSS2 - Can you answer these queries II

    GSS2 - Can you answer these queries II 题意: 给你1e51e51e5 的序列,每次询问区间l到rl到rl到r,每个相同的数只算一次的最大子段和. 思路: 乍一眼 ...

  9. 题解 SP2916 【GSS5 - Can you answer these queries V】

    前言 最近沉迷于数据结构,感觉数据结构很有意思. 正文 分析 先来分类讨论一下 1. x2<y1x2<y1x2<y1 如果 y1<x2y1<x2y1<x2 的话,答 ...

  10. GSS7 - Can you answer these queries VII 题解

    题目传送门 题目大意: 求树上最大子段和,带修. 如果做了gss系列的前六题,那么这题相信不难.用一个树链剖分维护这棵树即可. 但是细节比较烦. 具体做法:对于求 x x x到 y y y路径上的最大 ...

最新文章

  1. OpenWrt启动过程分析+添加自启动脚本【转】
  2. 如何在零停机的情况下迁移 Kubernetes 集群
  3. Echarts后台option对象
  4. ios添加设备真机测试,以及Undefined symbols for architecture x86_64:''错误
  5. Codeforces 408D Long Path (DP)
  6. 【教训】rm -fr ./* 教训
  7. label 阻止冒泡 防止点击label 触发2次事件
  8. 2021年度训练联盟热身训练赛第二场(ICPC North Central NA Contest 2019,南阳师范学院),签到题ABCDEFGIJ
  9. 【渝粤教育】电大中专建筑力学 (3)作业 题库
  10. @JoinColumn 详解
  11. Java 平衡二叉树和AVL
  12. 基于ssm java jsp的酒店管理系统 前后台
  13. wireshark之npcap-1.50及以上版本在winserver2008-r2-sp1和win7上的问题
  14. java2048朝代版代码_2048朝代版完整版
  15. js的onfocus与onblur的用法
  16. 小程序运营推广的方法
  17. linux安装gcc运行时库,现在可以在CentOS 8系统下用命令安装GCC 8.3.1版本
  18. DBG、DMB、DSB 和 ISB
  19. 记录使用scrapy爬取新闻网站最新新闻存入MySQL数据库,每天定时爬取自动更新
  20. 李翰卿治疗小儿五更咳嗽经验

热门文章

  1. lol微信登录服务器,LOL开启微信登录功能测试 绑定微信登陆方法一览
  2. 093 一个人的固执里,藏着低水平的认知
  3. 湖北大学知行学院考研计算机,我院2016届毕业生考研喜创佳绩
  4. 三目表达式 ---if--else的简写
  5. 微信收到消息很慢无法连接服务器,微信消息总是延迟接收怎么办?
  6. 三原色是红黄蓝对吗_为什么三原色是红黄蓝而?
  7. 日语 敬体 简体 作文 对话
  8. 共模和差模电感电路分析方法及思路
  9. 我的世界服务端java路径_我的世界服务端java路径咋样设置?
  10. Ubuntu20.04 虚拟机 联网