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 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...
随机推荐
- charles刷分微信跳一跳小程序对https的理解
以前以为只要安装了https 客户端与服务端的数据会被加密就安全了 事实上 只要任意一款抓包工具 并伪造证书 就可以解密这个被所谓https加密的数据 如 可以下载charles的根证书 作为伪 ...
- RAC 单节点实例异常关闭,关键报错ORA--29770
监控系统监控到RAC 的一个实例异常关闭 ,时间是凌晨1点多,还好没有影响到业务 之后就是分析原因 这套RAC搭建在虚拟化环境OS SUSE11 查看oracel alert log信息 Mon :: ...
- Python GIL、线程锁、信号量及事件
GIL是什么? GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码.有名的编 ...
- MAC 安装phantomjs
step1:下载压缩包http://phantomjs.org/ step2:解压缩,我是解压缩到/Users/gxy/software step3:写入配置路径,vi ~/.bash_profile ...
- Java并发实现线程阻塞原语LockSupport
LockSupport 和 CAS 是Java并发包中很多并发工具控制机制的基础,它们底层其实都是依赖Unsafe实现.LockSupport是用来创建锁和其他同步类的基本线程阻塞原语. 1.Lock ...
- Markdown Reader 插件改造
Markdown Reader 是一款比较好用的浏览markdown文件的chrome插件 插件地址:https://chrome.google.com/webstore/detail/markdow ...
- Ubuntu install JDK
1.#下载JDK,记住保存的目录 2. sudo mkdir /usr/java 3. sudo tar zxvf jdk-7u75-linux-x64.tar.gz -C /usr/java 4. ...
- Android实例1:button点击响应
个人网站http://www.ravedonut.com/ Layout xml文件 <RelativeLayout android:layout_width="wrap_conten ...
- Paint Tree
题意: 给定一棵n个点的树,给定平面上n个点,将n个点用线段连起来画成树的形状,使得不存在不在端点相交的线段,构造出一种情况. 解法: 首先观察我们常规画出来的树形图可知,树的子树是根据极角分开的,这 ...
- 性能测试之Jmeter学习(三)
一.Jmeter执行顺序规则: 元件执行顺序的规则很简单,在同一作用域名范围内,测试计划中的元件按照如下顺序执行. (1)配置元件(config elements ) (2)前置处理程序(Per-pr ...