Codeforces 438D The Child and Sequence - 线段树
At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at him. A lot of important things were lost, in particular the favorite sequence of Picks.
Fortunately, Picks remembers how to repair the sequence. Initially he should create an integer array a[1], a[2], ..., a[n]. Then he should perform a sequence of m operations. An operation can be one of the following:
- Print operation l, r. Picks should write down the value of
. - Modulo operation l, r, x. Picks should perform assignment a[i] = a[i] mod x for each i (l ≤ i ≤ r).
- Set operation k, x. Picks should set the value of a[k] to x (in other words perform an assignment a[k] = x).
Can you help Picks to perform the whole sequence of operations?
The first line of input contains two integer: n, m (1 ≤ n, m ≤ 105). The second line contains n integers, separated by space: a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ 109) — initial value of array elements.
Each of the next m lines begins with a number type
.
- If type = 1, there will be two integers more in the line: l, r (1 ≤ l ≤ r ≤ n), which correspond the operation 1.
- If type = 2, there will be three integers more in the line: l, r, x (1 ≤ l ≤ r ≤ n; 1 ≤ x ≤ 109), which correspond the operation 2.
- If type = 3, there will be two integers more in the line: k, x (1 ≤ k ≤ n; 1 ≤ x ≤ 109), which correspond the operation 3.
For each operation 1, please print a line containing the answer. Notice that the answer may exceed the 32-bit integer.
5 5 1 2 3 4 5 2 3 5 4 3 3 5 1 2 5 2 1 3 3 1 1 3
8 5
10 10 6 9 6 7 6 1 10 10 9 5 1 3 9 2 7 10 9 2 5 10 8 1 4 7 3 3 7 2 7 9 9 1 2 4 1 6 6 1 5 9 3 1 10
49 15 23 1 9
Consider the first testcase:
- At first, a = {1, 2, 3, 4, 5}.
- After operation 1, a = {1, 2, 3, 0, 1}.
- After operation 2, a = {1, 2, 5, 0, 1}.
- At operation 3, 2 + 5 + 0 + 1 = 8.
- After operation 4, a = {1, 2, 2, 0, 1}.
- At operation 5, 1 + 2 + 2 = 5.
题目大意 维护一个数列,有3种操作,分别是区间求和,区间取模和单点修改。
显然线段树(请不要问我为什么。。。学长的Tag打在那儿的)
区间求和和单点修改都是线段树的拿手好戏,但是对于区间取模似乎不是那么好做。考虑可以区间批量更新sum吗?显然不行。
但是考虑到这里只有单点修改,而且对一个大于模数的数取模,它的值至多为它原来的值的一半。
所以区间记录一个最大值剪枝,每次区间取模先判断是否有必要进行递归取模,如果有,就暴力递归下去,在底层修改。
Code
/**
* Codeforces
* Problem#438D
* Accepted
* Time: 436ms
* Memory: 8740k
*/
#include <bits/stdc++.h>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std; typedef class SegTreeNode {
public:
int maxv;
long long sum;
SegTreeNode *l, *r; SegTreeNode():maxv(), sum(), l(NULL), r(NULL) { } inline void pushUp() {
maxv = max(l->maxv, r->maxv);
sum = l->sum + r->sum;
}
}SegTreeNode; typedef class SegTree {
public:
SegTreeNode* root; SegTree():root(NULL) { }
SegTree(int n, int* a) {
build(root, , n, a);
} void build(SegTreeNode*& node, int l, int r, int* a) {
node = new SegTreeNode();
if(l == r) {
node->sum = node->maxv = a[l];
return;
}
int mid = (l + r) >> ;
build(node->l, l, mid, a);
build(node->r, mid + , r, a);
node->pushUp();
} void update(SegTreeNode*& node, int l, int r, int idx, int val) {
if(l == r) {
node->maxv = node->sum = val;
return;
}
int mid = (l + r) >> ;
if(idx <= mid) update(node->l, l, mid, idx, val);
else update(node->r, mid + , r, idx, val);
node->pushUp();
} void update(SegTreeNode*& node, int l, int r, int ql, int qr, int moder) {
if(l == r) {
node->maxv = (node->sum %= moder);
return;
}
int mid = (l + r) >> ;
if(qr <= mid && node->l->maxv >= moder) update(node->l, l, mid, ql, qr, moder);
else if(ql > mid && node->r->maxv >= moder) update(node->r, mid + , r, ql, qr, moder);
else if(qr > mid && ql <= mid) {
if(node->l->maxv >= moder)
update(node->l, l, mid, ql, mid, moder);
if(node->r->maxv >= moder)
update(node->r, mid + , r, mid + , qr, moder);
}
node->pushUp();
} long long query(SegTreeNode*& node, int l, int r, int ql, int qr) {
if(l == ql && r == qr) {
return node->sum;
}
int mid = (l + r) >> ;
if(qr <= mid) return query(node->l, l, mid, ql, qr);
if(ql > mid) return query(node->r, mid + , r, ql, qr);
return query(node->l, l, mid, ql, mid) + query(node->r, mid + , r, mid + , qr);
}
}SegTree; int n, m;
int* arr;
SegTree st;
inline void init() {
scanf("%d%d", &n, &m);
arr = new int[(n + )];
for(int i = ; i <= n; i++)
scanf("%d", arr + i);
st = SegTree(n, arr);
} inline void solve() {
int opt, a, b, c;
while(m--) {
scanf("%d%d%d", &opt, &a, &b);
if(opt == ) {
printf(Auto"\n", st.query(st.root, , n, a, b));
} else if(opt == ) {
scanf("%d", &c);
st.update(st.root, , n, a, b, c);
} else {
st.update(st.root, , n, a, b);
}
}
} int main() {
init();
solve();
return ;
}
Codeforces 438D The Child and Sequence - 线段树的更多相关文章
- CodeForces 438D The Child and Sequence (线段树 暴力)
传送门 题目大意: 给你一个序列,要求在序列上维护三个操作: 1)区间求和 2)区间取模 3)单点修改 这里的操作二很讨厌,取模必须模到叶子节点上,否则跑出来肯定是错的.没有操作二就是线段树水题了. ...
- CF(438D) The Child and Sequence(线段树)
题意:对数列有三种操作: Print operation l, r. Picks should write down the value of . Modulo operation l, r, x. ...
- 2018.07.23 codeforces 438D. The Child and Sequence(线段树)
传送门 线段树维护区间取模,单点修改,区间求和. 这题老套路了,对一个数来说,每次取模至少让它减少一半,这样每次单点修改对时间复杂度的贡献就是一个log" role="presen ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸
D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模
D. The Child and Sequence At the children's day, the child came to Picks's house, and messed his h ...
- 题解——CodeForces 438D The Child and Sequence
题面 D. The Child and Sequence time limit per test 4 seconds memory limit per test 256 megabytes input ...
- cf250D. The Child and Sequence(线段树 均摊复杂度)
题意 题目链接 单点修改,区间mod,区间和 Sol 如果x > mod ,那么 x % mod < x / 2 证明: 即得易见平凡, 仿照上例显然, 留作习题答案略, 读者自证不难. ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence (线段树)
题目链接:http://codeforces.com/problemset/problem/438/D 给你n个数,m个操作,1操作是查询l到r之间的和,2操作是将l到r之间大于等于x的数xor于x, ...
- Codeforces 438D The Child and Sequence
题意:给定一个n个数的序列,完成以下3个操作: 1.给定区间求和 2.给定区间对x取模 3.单点修改 对一个数取模,这个数至少折半.于是我们记一个最大值max,如果x>max则不做处理. #in ...
随机推荐
- cocos2d JS-(JavaScript) 几种循环遍历对象的比较
通常我们会用循环的方式来遍历数组.但是循环是 导致js 性能问题的原因之一.一般我们会采用下几种方式来进行数组的遍历: 方式1: for in 循环: var arr = [1,2,3,4,5]; v ...
- animation 老动画
关于设置跳跃: using System.Collections; using System.Collections.Generic; using UnityEngine; public class ...
- java virtual machine launcher Error:Could not create the Java Virtual Machine. Error:A Fatal exception has occurred,Program will exit.
Error:Could not create the Java Virtual Machine. Error:A Fatal exception has occurred,Program will e ...
- JavaScript循环和数组常用操作
while循环 语法: do while循环 语法:do{循环体}while(条件表达式); 特点:do while循环不管条件是否成立,无论如何循环体都会执行一次. 使用场合:用户输入密码,如果密码 ...
- 文件格式(图像 IO 14.3)
文件格式 图片加载性能取决于加载大图的时间和解压小图时间的权衡.很多苹果的文档都说PNG是iOS所有图片加载的最好格式.但这是极度误导的过时信息了. PNG图片使用的无损压缩算法可以比使用JPEG的图 ...
- 字符编码几个缩写 ACR CCS CEF CES TES
摘自https://zhuanlan.zhihu.com/p/27012967 5. 在Unicode Technical Report (UTR统一码技术报告) #17<UNICODE CHA ...
- Hive 修改表结构常用操作
添加列 add columns alter table table_name add columns (id int comment '主键ID' ) ; 默认在表所有字段之后,分区字段之前. 替换 ...
- HCatalog 学习之路
最近在使用sqoop把数据从hive数仓导出到mysql数据库中接触到了hcatalog,所以特意学习了解一下相关知识,据悉hcatalog还是apache顶级项目. 学习参考: HCatalog 介 ...
- byte以及UTF-8的转码规则
https://www.cnblogs.com/hell8088/p/9184336.html 多年来闲麻烦,只记录笔记,不曾编写BLOG,本文为原创,如需转载请标明出处 废话不说,直奔主题 asci ...
- [转载]Oracle中的NVL函数
Oracle中函数以前介绍的字符串处理,日期函数,数学函数,以及转换函数等等,还有一类函数是通用函数.主要有:NVL,NVL2,NULLIF,COALESCE,这几个函数用在各个类型上都可以. 下面简 ...