线段树 区间加 gcd 差分 小阳的贝壳
如果线段树要维护区间gcd 这个很简单,但是如果有了区间加,维护gcd 就比较麻烦了。
这个首先可以证明的是 gcd(x,y,z)=gcd(x,y-x,z-y) 这个可以推到 n 个
这个就和差分扯上关系了 可以看一下差分 差分传送门
上面的这两个博客基本上告诉我们这两个题目怎么写了。
首先我们对于每一个数进行处理,把这个数变成差分的形式,
因为最后的结果我们要 gcd(x,y-x,z-y) 所以我们要求和,还有求gcd ,这个就会有两个查询,一个查询sum,一个查询gcd
你看了差分的博客后你就发现,如果我们要给一段区间整体加上一个值,这个区间更新可以转化成差分的单点更新。
然后就是区间差值最大,这个很好求,因为我们每一个数本来放进去的就是区间的差分,所以这个相当于在求最大值。只是注意边界。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 2e5 + ;
int a[maxn];
struct node
{
int l, r;
int max, sum, val;
}tree[maxn*]; int gcd(int a,int b)
{
return b == ? a : gcd(b, a%b);
} void push_up(int id)
{
tree[id].max = max(abs(tree[id << ].max), abs(tree[id << | ].max));
tree[id].sum = tree[id << | ].sum + tree[id << ].sum;
tree[id].val = gcd(tree[id << ].val, tree[id << | ].val);
} void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
if(l==r)
{
tree[id].sum = tree[id].val = a[l];
tree[id].max = abs(a[l]);
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
push_up(id);
} int query_sum(int id,int x,int y)
{
int l = tree[id].l;
int r = tree[id].r;
if(x<=l&&y>=r)
{
return tree[id].sum;
}
int ans = ;
int mid = (l + r) >> ;
if (x <= mid) ans += query_sum(id << , x, y);
if (y > mid) ans += query_sum(id << | , x, y);
return ans;
} int query_val(int id,int x,int y)
{
int l = tree[id].l;
int r = tree[id].r;
if(x<=l&&y>=r)
{
return tree[id].val;
}
int ans = ;
int mid = (l + r) >> ;
if (x <= mid) ans = gcd(ans, query_val(id << , x, y));
if (y > mid) ans = gcd(ans, query_val(id << | , x, y));
return ans;
} int query_max(int id,int x,int y)
{
int l = tree[id].l;
int r = tree[id].r;
if(x<=l&&y>=r)
{
return tree[id].max;
}
int ans = ;
int mid = (l + r) >> ;
if (x <= mid) ans = max(ans, query_max(id << , x, y));
if (y > mid) ans = max(ans, query_max(id << | , x, y));
return ans;
} void update(int id,int pos,int x)
{
int l = tree[id].l;
int r = tree[id].r;
if(l==r)
{
tree[id].sum += x;
tree[id].val += x;
tree[id].max = abs(tree[id].val);
return;
}
int mid = (l + r) >> ;
if (pos <= mid) update(id << , pos, x);
else update(id << | , pos, x);
push_up(id);
} int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) scanf("%d", &a[i]);
for (int i = n; i >= ; i--) a[i] = a[i] - a[i - ];
build(, , n);
while (m--) {
int opt, l, r, x;
scanf("%d", &opt);
if(opt==)
{
scanf("%d%d%d", &l, &r, &x);
if (l > r) swap(l, r);
update(, l, x);
if(r+<=n) update(, r + , -x);
}
if(opt==)
{
scanf("%d%d", &l, &r);
if (l > r) swap(l, r);
int ans = ;
if(l!=r) ans = query_max(, l + , r);
printf("%d\n", ans);
}
if(opt==)
{
scanf("%d%d", &l, &r);
if (l > r) swap(l, r);
int ans = ;
int ex1 = query_sum(, , l);
int ex2 = query_val(, l + , r);
if (l == r) ans = ex1;
else ans = abs(gcd(ex1, ex2));
printf("%d\n", ans);
}
// if(opt==4)
// {
// scanf("%d", &l);
// printf("%d\n", query_sum(1, 1, l));
// }
}
return ;
}
gcd 线段树 差分
线段树 区间加 gcd 差分 小阳的贝壳的更多相关文章
- 【CF52C】Circular RMQ(线段树区间加减,区间最值)
给定一个循环数组a0, a1, a2, …, an-1,现在对他们有两个操作: Inc(le, ri, v):表示区间[le, ri]范围的数值增加v Rmq(le, ri):表示询问区间[le, r ...
- vijos 1659 河蟹王国 线段树区间加、区间查询最大值
河蟹王国 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 https://vijos.org/p/1659 Description 河蟹王国有一位河蟹国王,他 ...
- poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和
A Simple Problem with Integers Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...
- poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和(模板)
A Simple Problem with Integers Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- 2015 UESTC 数据结构专题B题 秋实大哥与花 线段树 区间加,区间查询和
B - 秋实大哥与花 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...
- COGS.1272.[AHOI2009]行星序列(线段树 区间加、乘、求和)
题目链接 //注意取模! #include<cstdio> #include<cctype> using namespace std; const int N=1e5+5; i ...
- hdu4521-小明系列问题——小明序列(线段树区间求最值)
题意:求最长上升序列的长度(LIS),但是要求相邻的两个数距离至少为d,数据范围较大,普通dp肯定TLE.线段树搞之就可以了,或者优化后的nlogn的dp. 代码为 线段树解法. #include ...
- 「模板」 线段树——区间乘 && 区间加 && 区间求和
「模板」 线段树--区间乘 && 区间加 && 区间求和 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long l ...
随机推荐
- java 代码执行cmd 返回值异常 (关于JAVA Project.waitfor()返回值是1)
关于JAVA Project.waitfor()返回值是1 0条评论 Project.waitfor()返回值是1,找了很久从网上没有发现关于1的说明. 这时对源代码调试了一下,发现Project ...
- I - Red and Black DFS
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A ...
- php+mysql数据库联合查询 left join 右侧数据重复问题
情况:多表联合查询(三表及以上联合查询) 分析: A left join B left join C left join D 假如: 表B.C.D都与表A关联查询 A left join B 4条数据 ...
- js输入框练习
这个就是一个输入框的小练习(也是第一次写这个东西) <!DOCTYPE html> <html lang="en"> <head> <me ...
- 高德局部刷新标记点,bug解决
将接口返回的经纬集合点在高德地图上标记展示, 如果实时刷新地图标记点,不加优化,则会造成过多的带宽消耗 所以,地图只需加载一次,局部更新标记点就好了 代码: <template> < ...
- 不停机还能替换代码?6年的 Java程序员表示不可思议
相信很多人都有这样一种感受,自己写的代码在开发.测试环境跑的稳得一笔,可一到线上就抽风,不是缺这个就是少那个反正就是一顿报错,而线上调试代码又很麻烦,让人头疼得很.不过, 阿里巴巴出了一款名叫Arth ...
- 基于layui,Jquery 表格动态编辑 设置 编辑值为 int 或者 double 类型及默认值
首先先推荐大家在看这篇笔记时,阅读过我写的这篇 Layui表格编辑[不依赖Layui的动态table加载] 阅读过上面那篇笔记之后呢,才能更好的理解我现在所要说的这个东西 接下来废话不多说,上代码. ...
- Win7+Linux双系统,完美解决删除Linux后出现的任何问题!
首先,进入到Win7,安装MiniTool Partition Wizard Home Edition删除掉Linux分区, 点Yes 然后选中 这里选中这个,重写MBR,开机神马grub神马问题都没 ...
- SpringBoot【新手学习记录篇】
1. 启动方式: 在idea中的application.java右键run as 命令行进入项目目录,使用命令 mvn spring-boot:run 使用mvn install进行打包,然后进入ta ...
- css3 文本控制自动换行
text-overflow:ellipsis; white-space:nowrap; overflow:hidden;