线段树 区间加 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 ...
随机推荐
- AJ学IOS(13)UI之UITableView学习(下)汽车名牌带右侧索引
AJ分享,必须精品 先看效果图 代码 ViewController #import "NYViewController.h" #import "NYCarGroup.h& ...
- Django开发文档-域用户集成登录
项目概述: 一般在企业中,用户以WINDOWS的域用户统一的管理,所以以Django快速开发的应用,不得不集成AD域登录. 网上一般采用django-python3-ldap的库来做集成登录,但是本方 ...
- 智能可视化搭建系统 Atom 服务架构演变
作者:凹凸曼 - Manjiz Atom 是什么?Atom 是集结业内各色资深电商行业设计师,提供一站式专业智能页面和小程序设计服务的平台.经过 2 年紧凑迭代,项目越来越庞大,需求不断变更优化,内部 ...
- [linux] [nginx] 一键安装web环境全攻略phpstudy版,超详细!
找到运行中的服务器(实例). 打开这个主要是看它的IP,是公网ip,公网ip,公网ip,重要的事情说三遍. 接下来我们可以不用在阿里云上操作了,直接用客户端操作,这两个客户端就是Xshell 5和Xf ...
- python 进阶篇 函数装饰器和类装饰器
函数装饰器 简单装饰器 def my_decorator(func): def wrapper(): print('wrapper of decorator') func() return wrapp ...
- Redis开发运维的陷阱及避坑指南
原文首发于博客园,作者:后青春期的Keats:地址:https://www.cnblogs.com/keatsCoder/ 转载请注明,谢谢! Linux 配置优化 我们在使用 Redis 过程中,可 ...
- 2、flink入门程序Wordcount和sql实现
一.DataStream Wordcount 代码地址:https://gitee.com/nltxwz_xxd/abc_bigdata 基于scala实现 maven依赖如下: <depend ...
- Redis来限制用户 ------------IP某个时间段内访问的次数
$redis = new Redis(); $redis->connect('127.0.0.1', 6379); //获取客户端真实ip地址 function get_real_ip(){ s ...
- 深入理解TCP建立和关闭连接
建立连接: 理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包含了自 ...
- cut,xargs,sort,tr,rename命令解析
cut 文件内容查看 显示行中的指定部分,删除文件中指定字段 显示文件的内容,类似于下的type命令. 语法: cut(选项)(参数) 选项: -b:仅显示行中指定直接范围的内容: -c:仅显示行中指 ...