BZOJ 5028 小Z的加油店

【题解】
本题要求求出区间内的各个元素通过加减之后能够得出的最小的数,那么根据裴蜀定理可知答案就是区间内各个元素的最大公约数。
那么本题题意化简成了维护一个序列,支持区间加上某个数以及查询区间元素的最大公约数。
我们要证明这样一个定理:
对于一个序列(a,b,c,d,...),gcd(a,b,c,d,...)=gcd(a,b-a,c-b,d-c,...),文字表述就是原序列的最大公约数等于序列差分后的最大公约数。
证明方法如下:
1,设t为序列(a,b,c,d,...)的公约数,a<b<c,b=k1*a+x1,c=k2*a+x2,
那么我们有t|a,t|b,t|c
所以有t|x1,t|x2
所以t|(x2-x1)
所以t|(k1-1)*a+x1,t|(k2-k1)*a+(x2-x1)
即t也是序列(a,b-a,c-b,...)的公约数
同理,(a,b,c,...)的任一公约数也是(a,b-a,c-b,...)的公约数。
2,设t为序列(a,b-a,c-b,...)的公约数,
那么有t|a, t|(k1-1)*a+x1, t|(k2-k1)*a+(x2-x1)
所以有t|x1,t|x2-x1
所以t|x2
所以t|a, t|k1*a+x1,t|k2*a+x2
即t也是序列(a,b,c,...)的公约数
同理,(a,b-a,c-b,...)的任一公约数也是(a,b,c,...)的公约数。
综上,gcd(a,b,c,...)=gcd(a,b-a,c-b,...).
证明完这个定理之后,我们就可以把题意化为求区间第一个元素与后面元素的差分值的GCD
我们先把原序列差分,线段树维护差分数组的GCD。因为我们已经进行了差分,所以区间加操作变成了点修改,可以直接在线段树上logn完成。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
#define rg register
#define N 100010
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((a[u].l+a[u].r)>>1)
using namespace std;
int n,m,v[N],c[N],t[N];
struct tree{
int l,r,g;
}a[N<<];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
int gcd(int x,int y){return y?gcd(y,x%y):x;}
void build(int u,int l,int r){
a[u].l=l; a[u].r=r;
if(l<r) build(ls,l,mid),build(rs,mid+,r),a[u].g=gcd(a[ls].g,a[rs].g);
else a[u].g=abs(c[l]);
}
void update(int u,int pos,int data){
if(a[u].l==a[u].r){
a[u].g=data; return;
}
update(pos<=mid?ls:rs,pos,data);
a[u].g=gcd(a[ls].g,a[rs].g);
}
int query(int u,int l,int r){
if(l<=a[u].l&&a[u].r<=r) return a[u].g;
int ret=; bool goleft=;
if(l<=mid) ret=query(ls,l,r),goleft=;
if(r>mid){
if(goleft) ret=gcd(ret,query(rs,l,r));
else ret=query(rs,l,r);
}
return ret;
}
inline void add(int x,int y){for(;x<=n+;x+=(x&-x)) t[x]+=y;}
inline int qsum(int x){int ret=; for(;x;x-=(x&-x)) ret+=t[x]; return ret;}
int main(){
n=read(); m=read();
for(rg int i=;i<=n;i++) v[i]=read(),c[i]=v[i]-v[i-],add(i,c[i]);
build(,,n);
while(m--){
int opt=read(),l=read(),r=read(); if(l>r) swap(l,r);
if(opt==){
if(l<r) printf("%d\n",gcd(qsum(l),query(,l+,r)));
else printf("%d\n",qsum(l));
}
else{
int del=read();
c[l]+=del; c[r+]-=del;
add(l,del); if(r<n) add(r+,-del);
update(,l,abs(c[l])); if(r<n) update(,r+,abs(c[r+]));
}
}
return ;
}
BZOJ 5028 小Z的加油店的更多相关文章
- bzoj 5028: 小Z的加油店——带修改的区间gcd
Description 小Z经营一家加油店.小Z加油的方式非常奇怪.他有一排瓶子,每个瓶子有一个容量vi.每次别人来加油,他会让 别人选连续一段的瓶子.他可以用这些瓶子装汽油,但他只有三种操作: 1. ...
- 【BZOJ】5028: 小Z的加油店
[算法]数学+线段树/树状数组 [题解] 首先三个操作可以理解为更相减损术或者辗转相除法(待证明),所以就是求区间gcd. 这题的问题在线段树维护gcd只能支持修改成一个数,不支持加一个数. 套路:g ...
- 5028: 小Z的加油店(线段树)
NOI2012魔幻棋盘弱化版 gcd(a,b,c,d,e)=gcd(a,b-a,c-b,d-c,e-d) 然后就可以把区间修改变成差分后的点修了. 用BIT维护原序列,线段树维护区间gcd,支持点修区 ...
- D - 小Z的加油店 线段树+差分+GCD
D - 小Z的加油店 HYSBZ - 5028 这个题目是一个线段树+差分+GCD 推荐一个差分的博客:https://www.cnblogs.com/cjoierljl/p/8728110.ht ...
- [BZOJ5028]小Z的加油店
[BZOJ5028]小Z的加油店 题目大意: 一个长度为\(n(n\le10^5)\)的数列,\(m(m\le10^5)\)次操作,支持区间加和区间\(\gcd\). 思路: 线段树维护差分,\(\g ...
- BZOJ 5028 小z的加油站
bzoj链接 Time limit 10000 ms Memory limit 262144 kB OS Linux 感想 树上动态gcd的第二题也好了. [x] BZOJ 2257 [JSOI200 ...
- bzoj5028小Z的加油店(线段树+差分)
题意:维护支持以下两种操作的序列:1 l r询问a[l...r]的gcd,2 l r x把a[l...r]全部+x 题解:一道经典题.根据gcd(a,b)=gcd(a-b,b)以及区间加可知,这题可以 ...
- 【bzoj5028】小Z的加油店 扩展裴蜀定理+差分+线段树
题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.$m$ 次操作,每次给 $[l,r]$ 内的瓶子容量增加 $ ...
- bzoj 4031: 小Z的房间 矩阵树定理
bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...
随机推荐
- python3 批量管理Linux服务器 下发命令与传输文件
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import paramiko import os, stat import sys import ope ...
- 连接mysql时提示java.sql.SQLException: Access denied for user 'root'@'DESKTOP-N2B2D9A' (using password: YES)
用root连接mysql时提示:访问被拒绝 检查一下mysql server是否开启,发现后台在运行着.. 然后查了一下mysql的用户表,发现root只能运行使用本地ip(localhost或者1 ...
- bzoj 1655: [Usaco2006 Jan] Dollar Dayz 奶牛商店【高精度+完全背包】
居然要用高精度! 懒得operator了,转移是裸的完全背包 #include<iostream> #include<cstdio> using namespace std; ...
- 洛谷 P1064 金明的预算方案(有依赖的背包问题)
题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今 ...
- iOS 关于文件操作 NSFileManager
创建文件夹 + (BOOL)creatDir:(NSString *)path { if (path.length==0) { return NO; } NSFileManager *fileMana ...
- JavaScript--History 对象
history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能. 注意:从窗口被打开的那一刻开始记录,每个浏览器窗口.每个标签页乃至每个框架,都有自己的history ...
- Hadoop Hive概念学习系列之hive的数据压缩(七)
Hive文件存储格式包括以下几类: 1.TEXTFILE 2.SEQUENCEFILE 3.RCFILE 4.ORCFILE 其中TEXTFILE为默认格式,建表时不指定默认为这个格式,导入数据时会直 ...
- Hive insert into directory 命令输出的文件没有列分隔符分析和解决
参考资料:http://stackoverflow.com/questions/16459790/hive-insert-overwrite-directory-command-output-is-n ...
- C# 堆VS栈 值类型VS引用类型
最近博客园上连续出现了几篇关于堆VS栈 值类型VS引用类型的文章. 一个是关于C# 堆VS栈的,深入浅出,动图清晰明了,链接如下 C#堆栈对比(Part One) C#堆栈对比(Part Two) C ...
- Spring Boot (31) 数据验证
曾经参数的验证是这样的: public String test(User user){ if(user == null){ throw new NullPointerException("u ...