Codeforces 1136E(转化+线段树维护)
虽然线段树比较显然但是发现a数组并不好维护。考虑将a转化为好维护的数组b。
方法
这里我将k[1]设为0,对应着$$a[1] + k[1] <= a[2]$$不难得出$$a[i] + k[i] <= a[i+1]$$
\]
所以设$$a[i] = b[i] + t[i],其中t[i]为k[i]的前缀和$$
以样例来说话:
| pos | 1 | 2 | 3 |
|---|---|---|---|
| a | 1 | 2 | 3 |
| k | 0 | 1 | -1 |
| t | 0 | 1 | 0 |
| b | 1 | 1 | 3 |
可以发现b数组是一个不下降的序列,原因是b是以a[1]为基石的,无论t数组是正是负,只会影响a数组的升降。这样我们就可以选择用线段树维护b,对于'+'操作,相当于修改线段树上的b数组:
1.在b[i]的位置加上x:
ll k = T.Query(i, i, 1) + x;
2.找到小于“修改后的b[i]”的第一个位置,因为只要保持b不下降就可以了,大于等于这个b[i]的位置不修改:
int pos = T.Position(i, n, 1, k);
3.区间修改:
T.Modify(i, pos, 1, k);
对于询问操作,就不难得出:$$\sum_{i = l}^ra[i] = \sum_{i = l}^r b[i]+t[i]$$
所以求t[i]时顺手求个t[i]的前缀和,这道题就完成了。
最后注意线段树的tag,要设成-inf,这题的数组值是正负皆可的,不能用是否为0来判断tag:
void Push_down(int p) {
if (t[p].tag > -INF) {
最终代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const ll INF = 1e18;
int n, q;
ll a[maxn], k[maxn], t[maxn], sum[maxn], b[maxn];
class SegmentTree {
public:
#define ls(p) p << 1
#define rs(p) p << 1 | 1
struct Node {
int l, r;
ll minn, sum, tag = -INF;
}t[maxn << 2];
void Push_up(int p) {
t[p].minn = min(t[ls(p)].minn, t[rs(p)].minn);
t[p].sum = t[ls(p)].sum + t[rs(p)].sum;
}
void Push_down(int p) {
if (t[p].tag > -INF) {
t[ls(p)].minn = t[rs(p)].minn = t[ls(p)].tag = t[rs(p)].tag = t[p].tag;
t[ls(p)].sum = t[p].tag * (t[ls(p)].r - t[ls(p)].l + 1);
t[rs(p)].sum = t[p].tag * (t[rs(p)].r - t[rs(p)].l + 1);
t[p].tag = -INF;
}
}
void Build(int l, int r, int p) {
t[p].l = l, t[p].r = r;
if (l == r) {
t[p].minn = t[p].sum = b[l];
return;
}
int mid = (l + r) >> 1;
Build(l, mid, ls(p));
Build(mid + 1, r, rs(p));
Push_up(p);
}
void Modify(int l, int r, int p, ll k) {
if (l <= t[p].l && t[p].r <= r) {
t[p].minn = t[p].tag = k;
t[p].sum = k * (t[p].r - t[p].l + 1);
return;
}
int mid = (t[p].l + t[p].r) >> 1;
Push_down(p);
if (l <= mid) Modify(l, r, ls(p), k);
if (mid < r) Modify(l, r, rs(p), k);
Push_up(p);
}
int Position(int l, int r, int p, ll k) {
if (t[p].minn < k && t[p].l == t[p].r) return t[p].l;
int mid = (t[p].l + t[p].r) >> 1;
Push_down(p);
if (t[rs(p)].minn < k) return Position(l, r, rs(p), k);
else return Position(l, r, ls(p), k);
}
ll Query(int l, int r, int p) {
if (l <= t[p].l && t[p].r <= r) return t[p].sum;
int mid = (t[p].l + t[p].r) >> 1;
Push_down(p);
if (l > mid) return Query(l, r, rs(p));
if (r <= mid) return Query(l, r, ls(p));
return Query(l, r, ls(p)) + Query(l, r, rs(p));
}
}T;
int main(int argc, char const *argv[]) {
ios_base::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 2; i <= n; i++)
cin >> k[i], t[i] = t[i - 1] + k[i], sum[i] = sum[i - 1] + t[i];
for (int i = 1; i <= n; i++)
b[i] = a[i] - t[i];
T.Build(1, n, 1);
for (cin >> q; q; q--) {
string op;
cin >> op;
if (op == "+") {
int i, x;
cin >> i >> x;
ll k = T.Query(i, i, 1) + x;
int pos = T.Position(i, n, 1, k);
T.Modify(i, pos, 1, k);
} else {
int l, r;
cin >> l >> r;
cout << T.Query(l, r, 1) + sum[r] - sum[l - 1] << endl;
}
}
return 0;
}
Codeforces 1136E(转化+线段树维护)的更多相关文章
- CodeForces - 1263E(线段树维护前缀和最值)
题意 https://vjudge.net/problem/CodeForces-1263E 您要设计一个只有一行的打字机,这一行的长度是无限大,一开始可以认为每个字符都是空.您的打字机有一个光标只指 ...
- Codeforces GYM 100114 D. Selection 线段树维护DP
D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...
- Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)
题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...
- Codeforces 834D The Bakery【dp+线段树维护+lazy】
D. The Bakery time limit per test:2.5 seconds memory limit per test:256 megabytes input:standard inp ...
- [Codeforces]817F. MEX Queries 离散化+线段树维护
[Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...
- codeforces Good bye 2016 E 线段树维护dp区间合并
codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...
- Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp
D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...
- Almost Regular Bracket Sequence CodeForces - 1095E (线段树,单点更新,区间查询维护括号序列)
Almost Regular Bracket Sequence CodeForces - 1095E You are given a bracket sequence ss consisting of ...
- Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)
Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...
随机推荐
- java基础以及操作Excle
今天把会经常用的几个集合的迭代方法又练习了一下,放在这里,经常复习! map集合迭代 /*** 迭代map[1]*/ for (Integer key : map.keySet()) {//迭代key ...
- awk实现求和、平均、最大值和最小值的计算操作
0.准备和数据文件 比如有一个数据文件,只有一列(在之前可以通过各种手段过滤出只有数字这一列),比如操作的响应时间 Txt代码 490898 1189235 20212 1494270 14 ...
- myeclipse配置
windows->preference->MyEclipse->servers->tomcat 选项下 Tomcat 6.x 点 enable 设置tomcat directo ...
- 【转】Cache Buffer Chain 第三篇
文章转自:http://oracle.chinaitlab.com/induction/862509.html,文章前部分转载,后部分自己加上的. Oracle数据库只读模式的CACHE BUFFER ...
- AngularJS系统学习之Directive(指令)
本文转自https://www.w3ctech.com/topic/1612 原文作者: Nicolas Bevacqua 原文:AngularJS’ Internals In Depth, Part ...
- IOS远程推送证书的制作步骤
今天还在看环信的使用方法,在环信的官网上发现了这组制作远程推送证书的一组图片,正好之前本人没有写过关于远程证书的笔记,这里要写一篇博文,整理一下远程推送证书的制作流程,尽管如此,本篇博文依然是作者原创 ...
- java中有关socket通信的学习笔记
最近做的项目中使用到了一些基于java的socket长连接的一些功能,用来穿透有关行业的网闸.用到了也就学习了一下,下面是对学习内容的一个笔记,记录一下也希望有兴趣的同学可以参考一下,加深对javas ...
- 20个Flutter实例视频教程-第02节: 底部导航栏制作-2
视频地址: https://www.bilibili.com/video/av39709290?p=2 博客地址: https://jspang.com/post/flutterDemo.html#t ...
- ubuntu 安装 lamp 和配置虚拟机
1:sudo passwd root #设定root密码 su 切换 exit 退出 ,或者 普通用户下 加sudo 2:sudo apt-get update #更新软件列表 3:sudo ...
- jQuery 实现网页跳转或用命令打开指定网页!
Jquery实现网页跳转或用命令打开指定网页! location.href = "www.baidu.com"; location.href = "aa.aspx&quo ...