线段树 区间加 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 ...
随机推荐
- Xray安装与使用
0×00 Xray简介 xray是从长亭洞鉴核心引擎中提取出的社区版漏洞扫描神器,支持主动.被动多种扫描方式,自备盲打平台.可以灵活定义 POC,功能丰富,调用简单,支持 Windows / macO ...
- AJ学IOS 之ipad开发qq空间项目横竖屏幕适配
AJ分享,必须精品 一:效果图 先看效果 二:结构图 如图所示: 其中用到了UIView+extension分类 Masonry第三方框架做子控制器的适配 NYHomeViewController对应 ...
- AJ学IOS(31)UI之Quartz2D图形上下文栈
AJ分享,必须精品 首先,前面博客说过.qurza2d的上下文中有绘图信息和绘图的属性. 但是他是怎么绘制到上下午中的呢? 我们画图时候一半会用这三个步骤: (1)获取上下文 (2)绘图 (3)渲染 ...
- PLSQL Developer 中文乱码踩坑记
环境 操作系统版本: Windows 7 PL/SQL 版本: 12.0.1.1814 原因 由于 Oracle 服务器端和客户端字符集编码不一致引起的. 注意点 写在最前面,减少踩坑!!! 网上教程 ...
- DES原理及代码实现
一.DES基础知识DES技术特点 DES是一种用56位密钥来加密64位数据的方法 DES采取了分组加密算法:明文和密文为64位分组长度 DES采取了对称算法:加密和解密除密钥编排不同外,使 ...
- [腾讯云]简单在腾讯云 CenTOS7.0 安装Nginx,Mysql(MariaDB),Memcache,解析PHP!
1.安装LNMP之前要安装EPEL,以便安装源以外的软件,如Nginx,phpMyAdmin等. yum install epel-release 2.安装Nginx a) yum install n ...
- 神奇的Kivy,让Python快速开发移动app
随着移动互联网的不断发展,手机.Pad等移动终端已经被普遍使用,充斥在人们的工作.学习和生活中,越来越多的程序都转向移动终端,各类app应用相拥而至. Kivy作为Python的Android和IOS ...
- 编程语言千千万,为什么学习Python的占一半?
如果让你从数百种的编程语言中选择一个入门语言?你会选择哪一个? 是应用率最高.长期霸占排行榜的常青藤 Java?是易于上手,难以精通的 C?还是在游戏和工具领域仍占主流地位的 C++?亦或是占据 Wi ...
- 从零开始学习docker之在docker中搭建redis(单机)
docker搭建redis 一.环境准备 云环境:CentOS 7.6 64位 二.下载镜像 从docker hub中找到redis镜像 传送门------https://hub.docker.com ...
- Git (一)预设环境和免密登录
背景 一直用的svn,这段时间换了之后才发现git的强大功能.缺点就是可能上手比较难一点. 接下来就带你Git入门 Git是什么? Git是目前世界上最先进的分布式版本控制系统 Git有什么特点?好用 ...