小阳的贝壳

如果线段树要维护区间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. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(六)之Initialization & Cleanup

    Two of these safety issues are initialization and cleanup. initialization -> bug cleanup -> ru ...

  2. PLSQL Developer 中文乱码踩坑记

    环境 操作系统版本: Windows 7 PL/SQL 版本: 12.0.1.1814 原因 由于 Oracle 服务器端和客户端字符集编码不一致引起的. 注意点 写在最前面,减少踩坑!!! 网上教程 ...

  3. vue路由中 Navigating to current location ("/router") is not allowed

    报错原因:多次点击同一路由,导致路由被多次添加 解决方法: router/index中添加以下代码: //router/index.js Vue.use(VueRouter) //导入vue路由 co ...

  4. 云开发静态网站托管现已支持 Angular 应用

    云开发静态托管是云开发提供的静态网站托管的能力,静态资源(HTML.CSS.JavaScript.字体等)的分发由腾讯云对象存储 COS 和拥有多个边缘网点的腾讯云 CDN 提供支持. 在云开发静态托 ...

  5. react: typescript jest && enzyme

    Install Jest 1.install jest dependencies jest @types/jest ts-jest -D 2.jest.config.js module.exports ...

  6. pytorch 中模型的保存与加载,增量训练

     让模型接着上次保存好的模型训练,模型加载 #实例化模型.优化器.损失函数 model = MnistModel().to(config.device) optimizer = optim.Adam( ...

  7. 13206抢票代码 py

    抢票代码 https://github.com/Bingshuli/12306Python 谷歌驱动 http://chromedriver.storage.googleapis.com/index. ...

  8. 闲聊http1.1的6个方法

    GET :获取资源GET 方法用来请求访问已被 URI 识别的资源.指定的资源经服务器端解析后返回响应内容. POST :传输实体主体POST 方法用来传输实体的主体.虽然用 GET 方法也可以传输实 ...

  9. python学习14集合

    '''''''''集合:set1.定义:是一个无序的不重复元素序列.2.表示:大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用 ...

  10. ERC20 Short Address Attack

    ERC20 Short Address Attack 什么是ERC20 Application Binary Interface(ABI) ERC20 Short Address Attack 开始攻 ...