小阳的贝壳

如果线段树要维护区间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 差分 小阳的贝壳的更多相关文章

  1. 【CF52C】Circular RMQ(线段树区间加减,区间最值)

    给定一个循环数组a0, a1, a2, …, an-1,现在对他们有两个操作: Inc(le, ri, v):表示区间[le, ri]范围的数值增加v Rmq(le, ri):表示询问区间[le, r ...

  2. vijos 1659 河蟹王国 线段树区间加、区间查询最大值

    河蟹王国 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 https://vijos.org/p/1659 Description 河蟹王国有一位河蟹国王,他 ...

  3. 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 ...

  4. 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 ...

  5. HDU 5828 Rikka with Sequence(线段树区间加开根求和)

    Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...

  6. 2015 UESTC 数据结构专题B题 秋实大哥与花 线段树 区间加,区间查询和

    B - 秋实大哥与花 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...

  7. COGS.1272.[AHOI2009]行星序列(线段树 区间加、乘、求和)

    题目链接 //注意取模! #include<cstdio> #include<cctype> using namespace std; const int N=1e5+5; i ...

  8. hdu4521-小明系列问题——小明序列(线段树区间求最值)

    题意:求最长上升序列的长度(LIS),但是要求相邻的两个数距离至少为d,数据范围较大,普通dp肯定TLE.线段树搞之就可以了,或者优化后的nlogn的dp. 代码为  线段树解法. #include ...

  9. 「模板」 线段树——区间乘 && 区间加 && 区间求和

    「模板」 线段树--区间乘 && 区间加 && 区间求和 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long l ...

随机推荐

  1. OpenWrite 编辑器如何配置七牛云图床

    感谢用户 mutiantong.cn 的创作分享,原文链接:https://www.jianshu.com/p/29f33ca6e491 1. 配置七牛云 1.1 通过七牛云链接购买七牛云对象存储, ...

  2. tf.nn.dropout 激活函数

    tf.nn.dropout(x,keep_prob,noise_shape=None,seed=None,name=None) 参数: x:一个浮点型Tensor. keep_prob:一个标量Ten ...

  3. 全网最全C#实习面试题目

    整个内容是我在春招面试时候整理的一些题目,里面涵盖有网上搬运的(由于当时没有记录来源,如果有转载没标注来源,请与我联系),还有我面试到的.整个排版很乱,后期我会一步一步整理.整个内容大概快有两万字.整 ...

  4. 格式化启动盘win10

    我这个(U盘)磁盘被分成了两个区,不能直接格式化 第一步: 第二步: 删除完了之后,选择格式化,ok. 说明:格式化时要选择系统. 常规NTFS  缺点:老设备,比如打印机,监控机识别不了. FAT系 ...

  5. linux常用命令--文件搜索

    find / -name file1 从 '/' 开始进入根文件系统搜索文件和目录 find / -user user1 搜索属于用户 'user1' 的文件和目录 find /home/user1 ...

  6. MVC-路由扩展-限制浏览器

    根据路由原理,MVC每次都会走获取路由上下文数据. 自定义Route 调用,以及完善其他代码 运行结果,当在谷浏览器执行时:

  7. Java 中正则表达式使用

    正则表达式基本用法: 测试代码: @Test public void test01() { String str = "adsfd##4324"; // 创建正则表达式对象 Pat ...

  8. java 容器(collection)--ArrayList 常用方法分析 源码分析

    ArrayList 介绍 打开jdk源码看看官方文档的介绍 粗糙的翻译下大致意思是: List接口的可调整大小的数组实现.实现了所有可选的列表操作,并允许所有元素,包括 null .除了实现List接 ...

  9. Java 排序算法-冒泡排序及其优化

    Java 排序算法-冒泡排序及其优化 什么是冒泡排序 基本写法 优化后写法 终极版本 源码及测试 什么是冒泡排序 这里引用一下百度百科上的定义: 冒泡排序(Bubble Sort),是一种计算机科学领 ...

  10. 8个超好用的Python内置函数,提升效率必备(小白必看)

    python中有许多内置函数,不像print那么广为人知,但它们却异常的强大,用好了可以大大提高代码效率. 这次来梳理下8个好用的python内置函数. 1.set() 当需要对一个列表进行去重操作的 ...