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 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...
随机推荐
- 高精度乘法(FFT)
学会了FFT之后感觉自己征服了世界! 当然是幻觉... 不过FFT还是很有用的,在优化大规模的动规问题的时候有极大效果. 一般比较凶残的计数动规题都需要FFT(n<=1e9). 下面是高精度乘法 ...
- yii中调取字段名称时label与labelEx的区别
$form = $this->beginWidget('CActiveForm',array('id' => 'userRegisterForm')); echo $form->la ...
- Android自动化测试怎么填写Xpath
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA5sAAAJYCAIAAABjAmXpAAAgAElEQVR4nOzdeZhb5Z0veNV/M88sz7 ...
- [ZJOI 2012] 网络
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2816 [算法] 对每种颜色的边建一棵LCT , 维护联通性即可 时间复杂度 : O( ...
- conditon_variable(条件变量)用于线程间同步
conditon_variable(条件变量)用于线程间同步 condition_variable有5个函数,函数名及对应的功能如下: wait阻塞自己,等待唤醒 wait_for阻塞自己,等待唤醒, ...
- 【网络爬虫】【java】微博爬虫(五):防止爬虫被墙的几个技巧(总结篇)
爬虫的目的就是大规模地.长时间地获取数据,跟我们正常浏览器获取数据相比,虽然机理相差不大,但总是一个IP去爬网站,大规模集中对服务器访问,时间一长就有可能被拒绝.关于爬虫长时间爬取数据,可能会要求验证 ...
- 【Linux学习】Linux文件系统4—Linux文件硬链接与软连接
Linux文件系统4-Linux文件硬链接与软连接 inode:索引节点 (连接文件)link 一.文件硬链接 1.Linux文件系统中,inode只相同的文件是硬链接文件 2.不同文件名,inode ...
- 极客时间_Vue开发实战_06.Vue组件的核心概念(2):事件
06.Vue组件的核心概念(2):事件 通过emit传递给父组件 我们点击了重置失败,上层的div的click=handleDivClick是接收不到.重置失败的点击的行为的 通常情况下,你不用.st ...
- CCF 201509-1 数列分段 (水题)
问题描述 给定一个整数数列,数列中连续相同的最长整数序列算成一段,问数列中共有多少段? 输入格式 输入的第一行包含一个整数n,表示数列中整数的个数. 第二行包含n个整数a1, a2, …, an,表示 ...
- 优化jQuery选择器
优化jQuery选择器 选择优化比以前更加重要,因为越来越多的浏览器实现了queryselectorall()并承担了将jQuery选择器转移到浏览器的责任.记住这些小技巧可以让你轻松突破学习选择器时 ...