区间加值,区间gcd, 牛客949H
牛客小白月赛16H 小阳的贝壳
题意
维护一个数组,支持以下操作:
1: 区间加值
2: 询问区间相邻数差的绝对值的最大值
3: 询问区间gcd
题解
设原数组为\(a\), 用线段树维护\(b[i] = a[i] - a[i - 1]\),
线段树维护三个值:min, max, gcd
对于操作1:
L 位置加上x, R + 1位置减去x
对于操作2:
查询区间(L + 1, R) 的 min, max, 取绝对值大者
对于操作3:
考虑gcd的性质
\(gcd(a, b, c, d, ...) = gcd(a, b - a, c - b, d - c, ...)\)
查询区间(L + 1, R) 的 gcd, 就是\(gcd(b - a, c - b, d - c, ...)\)
然后用另一个东西维护原来的a数列
可以用另一颗线段树lazy标记维护
我用的是树状数组差分,将区间更新和单点查询转化为单点更新和前缀和查询
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int mx[N << 2], mn[N << 2], g[N << 2], c[N], a[N], b[N];
int n, m, op, l, r, x;
void add(int pos, int val) {
for(; pos <= n; pos += pos & -pos)
c[pos] += val;
}
int ask(int pos) {
int ans = 0;
for(; pos; pos -= pos & -pos)
ans += c[pos];
return ans;
}
void pushup(int rt) {
mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
mn[rt] = min(mn[rt << 1], mn[rt << 1 | 1]);
g[rt] = __gcd(g[rt << 1], g[rt << 1 | 1]);
}
void build(int rt, int l, int r) {
if(l == r) {
mx[rt] = mn[rt] = g[rt] = b[l];
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushup(rt);
}
void update(int rt, int l, int r, int pos, int val) {
if(l == r) {
mx[rt] += val;
mn[rt] += val;
g[rt] += val;
return;
}
int mid = l + r >> 1;
if(pos <= mid)
update(rt << 1, l, mid, pos, val);
else
update(rt << 1 | 1, mid + 1, r, pos, val);
pushup(rt);
}
int querymax(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R) {
return max(abs(mn[rt]), abs(mx[rt]));
}
int mid = l + r >> 1, ans = 0;
if(L <= mid)
ans = max(ans, querymax(rt << 1, l, mid, L, R));
if(R > mid)
ans = max(ans, querymax(rt << 1 | 1, mid + 1, r, L, R));
return ans;
}
int querygcd(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R) {
return g[rt];
}
int mid = l + r >> 1, ans = 0;
if(L <= mid)
ans = __gcd(ans, querygcd(rt << 1, l, mid, L, R));
if(R > mid)
ans = __gcd(ans, querygcd(rt << 1 | 1, mid + 1, r, L, R));
return abs(ans);
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
add(i, a[i] - a[i - 1]);
b[i] = a[i] - a[i - 1];
}
build(1, 1, n);
while(m--) {
scanf("%d%d%d", &op, &l, &r);
if(op == 1) {
scanf("%d", &x);
add(l, x);
update(1, 1, n, l, x);
if(r != n) {
add(r + 1, -x);
update(1, 1, n, r + 1, -x);
}
}
else if(op == 2) {
if(l == r)
puts("0");
else
printf("%d\n", querymax(1, 1, n, l + 1, r));
}
else {
int a = ask(l), b;
if(l == r)
b = 0;
else
b = querygcd(1, 1, n, l + 1, r);
printf("%d\n", __gcd(a, b));
}
}
return 0;
}
区间加值,区间gcd, 牛客949H的更多相关文章
- 二叉树中和为某一值的路径 牛客网 程序员面试金典 C++ Python
二叉树中和为某一值的路径 牛客网 程序员面试金典 题目描述 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一 ...
- HDU 3577 Fast Arrangement ( 线段树 成段更新 区间最值 区间最大覆盖次数 )
线段树成段更新+区间最值. 注意某人的乘车区间是[a, b-1],因为他在b站就下车了. #include <cstdio> #include <cstring> #inclu ...
- cf834D(dp+线段树区间最值,区间更新)
题目链接: http://codeforces.com/contest/834/problem/D 题意: 每个数字代表一种颜色, 一个区间的美丽度为其中颜色的种数, 给出一个有 n 个元素的数组, ...
- HihoCoder1333 :平衡树(splay+lazy)(区间加值,区间删除)
描述 小Ho:好麻烦啊~~~~~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊!前几天老师让我帮忙管理一下团队的人员,但是感觉好难啊. 小Hi:说来听听? 小Ho:事情是这样的.我们有一个运动同好会 ...
- POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)
题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS Memory Limit ...
- 线段树 区间加 gcd 差分 小阳的贝壳
小阳的贝壳 如果线段树要维护区间gcd 这个很简单,但是如果有了区间加,维护gcd 就比较麻烦了. 这个首先可以证明的是 gcd(x,y,z)=gcd(x,y-x,z-y) 这个可以推到 n 个 ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- 【BZOJ】1798: [Ahoi2009]Seq 维护序列seq 线段树多标记(区间加+区间乘)
[题意]给定序列,支持区间加和区间乘,查询区间和取模.n<=10^5. [算法]线段树 [题解]线段树多重标记要考虑标记与标记之间的相互影响. 对于sum*b+a,+c直接加上即可. *c后就是 ...
- 线段树_区间加乘(洛谷P3373模板)
题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...
随机推荐
- 19-10-29-Night-X
布谷. 欢迎大家来不耻下问. 这里是正解不会,暴力写跪,乱搞鸡肋的某虻 . 好想放假啊!!!! 话说猫厂现在产量低迷…… ZJ一下: T1,三维偏序,只码了$\Theta(N^2)$暴力 T2,暴力愉 ...
- 【breathandlife】气势磅礴、比较好听的旋律有哪些?
[breathandlife]气势磅礴.比较好听的旋律有哪些? 分享:yunbest作者:来源:2015-10-26 专题:breathandlife [breathandlife]气势磅礴.比较好听 ...
- 《DSP using MATLAB》Problem 8.29
来汉有一月,往日的高温由于最近几个台风沿海登陆影响,今天终于下雨了,凉爽了几个小时. 接着做题. %% ------------------------------------------------ ...
- vue 模版组件用法
第一种 //首先,别忘了引入vue.js <div id="user_name_01"></div> <script src="../nod ...
- ssh 免密码登入
1.普通免密码登入 (1) 生成秘钥 [root@vick ~]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter f ...
- session中load()跟get()的区别
1.相同点:Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象. 2.区别在于: (1)如果未能发现符合条件的记录,get方法返回null,而l ...
- mysql基础教程(三)-----增删改、子查询、创建管理表、约束和分页
插入 INSERT语句语法 从其它表中拷贝数据 • 不必书写 VALUES 子句. • 子查询中的值列表应与 INSERT 子句中的列名对应 update语句 • 可以一次更新多条数据. • 如果需要 ...
- 获取请求header的各种方法
部分代码非原创 不定期更新 PHP function get_all_header() { // 忽略获取的header数据.这个函数后面会用到.主要是起过滤作用 $ignore = array(' ...
- python进阶_浅谈面向对象进阶
python进阶_浅谈面向对象进阶 学了面向对象三大特性继承,多态,封装.今天我们看看面向对象的一些进阶内容,反射和一些类的内置函数. 一.isinstance和issubclass class F ...
- Shell执行SQL,并存入变量
shell的语法还是比较严格的(比如变量赋值,两边不能用等号) #!/bin/bash ids=$(mysql -h172. -uroot -p1qaz@WSX -N -e "select ...