题目传送

虽然线段树比较显然但是发现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. [RK3288][Android6.0] 调试笔记 --- 移除uboot和kernel开机logo【转】

    本文转载自:http://blog.csdn.net/kris_fei/article/details/71600690 Platform: RockchipOS: Android 6.0Kernel ...

  2. ARCGIS 发布TIF,金字塔文件是否Server自动生成。

    经过发布一个TIF带OVR的服务TIF_OVR, 和一个不带金字塔的TIF服务TIF_WITHOUT_OVR. 证实,在..\arcgisserver\directories\arcgissystem ...

  3. x264 FFmpeg Options Guide

    https://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping x264 FFmpeg Options Guide Please Not ...

  4. IOS下WEBVIEW 的javascript数组与json定义 及交互

    最近在折腾IOS新闻浏览客户端,当中需要用到webview传递JSON数据到IOS上,然后在IOS上解析.刚入门IOS不久,看了不少的书,但都是囫囵吞枣.在开发过程中,遇到不少问题.开发环境mac m ...

  5. Flask-SQLAlchemy配置

    下面是 Flask-SQLAlchemy 中存在的配置值.Flask-SQLAlchemy 从您的 Flask 主配置中加载这些值. 注意其中的一些在引擎创建后不能修改,所以确保尽早配置且不在运行时修 ...

  6. c++再探string之eager-copy、COW和SSO方案

    在牛客网上看到一题字符串拷贝相关的题目,深入挖掘了下才发现原来C++中string的实现还是有好几种优化方法的. 原始题目是这样的: 关于代码输出正确的结果是()(Linux g++ 环境下编译运行) ...

  7. pycharm常用快捷键和自定义快捷键

     默认快捷键 编辑类: Ctrl + Space 基本的代码完成(类.方法.属性)Ctrl + Alt + Space 类名完成Ctrl + Shift + Enter 语句完成Ctrl + P 参数 ...

  8. [置顶] 谈EXPORT_SYMBOL使用

    转自:http://blog.csdn.net/macrossdzh/article/details/4601648 EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static ...

  9. bzoj2718

    二分图匹配 首先有个定理:最长反链=最小链覆盖 最小链覆盖可以重复经过点 所以我们不能直接建图 那么我们用floyd判断是否相连 然后建图就行了 #include<bits/stdc++.h&g ...

  10. A-Z,a-z,0-9的unicode编码表

    1.转自:https://blog.csdn.net/fedawn/article/details/7307993 A-Z 的 Unicode 字符编码表     十进制  十六进制 1.“A”的 U ...