题目传送

虽然线段树比较显然但是发现a数组并不好维护。考虑将a转化为好维护的数组b。

方法

这里我将k[1]设为0,对应着$$a[1] + k[1] <= a[2]$$不难得出$$a[i] + k[i] <= a[i+1]$$

\[a[i]+k[i]+k[i+1] <=a[i+2]
\]

所以设$$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(转化+线段树维护)的更多相关文章

  1. CodeForces - 1263E(线段树维护前缀和最值)

    题意 https://vjudge.net/problem/CodeForces-1263E 您要设计一个只有一行的打字机,这一行的长度是无限大,一开始可以认为每个字符都是空.您的打字机有一个光标只指 ...

  2. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  3. Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)

    题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...

  4. 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 ...

  5. [Codeforces]817F. MEX Queries 离散化+线段树维护

    [Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...

  6. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  7. 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 ...

  8. Almost Regular Bracket Sequence CodeForces - 1095E (线段树,单点更新,区间查询维护括号序列)

    Almost Regular Bracket Sequence CodeForces - 1095E You are given a bracket sequence ss consisting of ...

  9. Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)

    Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...

随机推荐

  1. 不使用库函数,编写函数int strcmp(char *source, char *dest) 相等返回0,不等返回-1【转】

    本文转载自:http://www.cppblog.com/mmdengwo/archive/2011/04/14/144253.aspx #include <stdio.h>#includ ...

  2. jquery特效(4)—轮播图②(定时自动轮播)

    周末出去逛完街,就回公司好好地研究代码了,也算是把定时自动轮播程序写出来了,特意说明一下,这次的轮播图是在昨天随笔中jquery特效(3)—轮播图①(手动点击轮播)的基础上写出来的,也就是本次随笔展示 ...

  3. Technocup 2017 - Elimination Round 2 C. Road to Cinema —— 二分

    题目链接:http://codeforces.com/problemset/problem/729/C C. Road to Cinema time limit per test 1 second m ...

  4. 学习c编程的第二天

    函数又叫方法,是实现某项功能或完成某项任务的代码块 #include<stdio.h>void show(){ printf("I like c language"); ...

  5. 清理html中空白符/空格/换行在行内元素中产生的间距

    问题:行内元素之间产生间隔 原因:换行符,Tab制表符,空格产生间隔 解决方法: 1.行内元素写成一行 2.设置font-size为0px 把父级文本设置为0px; 再为需要显示文字的行内元素设置文字 ...

  6. Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

  7. Anaconda tensorflow 安装笔记

    1.安装步骤: (1)Anaconda下载Anaconda 安装包可以到 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 下载.ps:也可 ...

  8. mysql 入门 1

    连接mysql服务器 mysql -h localhost -u username -ppasswd 1.查看服务器存在的库 show databases; 2.创建数据库 create databa ...

  9. SSIS 增量更新

    本文转自 http://sqlblog.com/blogs/andy_leonard/archive/2007/07/09/ssis-design-pattern-incremental-loads. ...

  10. mysql server安装(windows)

    1 在 https://dev.mysql.com/downloads/mysql/ 上下载mysql压缩包 2 解压,并把bin目录加入环境变量 3 初始化,完成后会在mysql根目录下生成data ...