【题解】

  本题要求求出区间内的各个元素通过加减之后能够得出的最小的数,那么根据裴蜀定理可知答案就是区间内各个元素的最大公约数。

  那么本题题意化简成了维护一个序列,支持区间加上某个数以及查询区间元素的最大公约数。

  我们要证明这样一个定理:

    对于一个序列(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的加油店的更多相关文章

  1. bzoj 5028: 小Z的加油店——带修改的区间gcd

    Description 小Z经营一家加油店.小Z加油的方式非常奇怪.他有一排瓶子,每个瓶子有一个容量vi.每次别人来加油,他会让 别人选连续一段的瓶子.他可以用这些瓶子装汽油,但他只有三种操作: 1. ...

  2. 【BZOJ】5028: 小Z的加油店

    [算法]数学+线段树/树状数组 [题解] 首先三个操作可以理解为更相减损术或者辗转相除法(待证明),所以就是求区间gcd. 这题的问题在线段树维护gcd只能支持修改成一个数,不支持加一个数. 套路:g ...

  3. 5028: 小Z的加油店(线段树)

    NOI2012魔幻棋盘弱化版 gcd(a,b,c,d,e)=gcd(a,b-a,c-b,d-c,e-d) 然后就可以把区间修改变成差分后的点修了. 用BIT维护原序列,线段树维护区间gcd,支持点修区 ...

  4. D - 小Z的加油店 线段树+差分+GCD

    D - 小Z的加油店 HYSBZ - 5028   这个题目是一个线段树+差分+GCD 推荐一个差分的博客:https://www.cnblogs.com/cjoierljl/p/8728110.ht ...

  5. [BZOJ5028]小Z的加油店

    [BZOJ5028]小Z的加油店 题目大意: 一个长度为\(n(n\le10^5)\)的数列,\(m(m\le10^5)\)次操作,支持区间加和区间\(\gcd\). 思路: 线段树维护差分,\(\g ...

  6. BZOJ 5028 小z的加油站

    bzoj链接 Time limit 10000 ms Memory limit 262144 kB OS Linux 感想 树上动态gcd的第二题也好了. [x] BZOJ 2257 [JSOI200 ...

  7. bzoj5028小Z的加油店(线段树+差分)

    题意:维护支持以下两种操作的序列:1 l r询问a[l...r]的gcd,2 l r x把a[l...r]全部+x 题解:一道经典题.根据gcd(a,b)=gcd(a-b,b)以及区间加可知,这题可以 ...

  8. 【bzoj5028】小Z的加油店 扩展裴蜀定理+差分+线段树

    题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.$m$ 次操作,每次给 $[l,r]$ 内的瓶子容量增加 $ ...

  9. bzoj 4031: 小Z的房间 矩阵树定理

    bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...

随机推荐

  1. 如何在linux 32位机器编译64位程序

    编译64位程序,不一定要编译机器是64位的,但是32位机器默认安装的gcc编译环境还是不能用来编译64位程序. 编译64位程序,需要加上-m64编译器参数,默认安装的gcc已经支持该参数,但是缺少64 ...

  2. uva11542

    https://vjudge.net/problem/UVA-11542 xor高斯消元... 答案为2^f-1 其实书上有一个问题 样例有3种情况,其中4,6,15是绑在一起的,也就是他们必须满足一 ...

  3. IDEA hadoop MapReduce 环境配置

    1.下载,安装,配置好Hadoop 2.在IDEA中执行MapReduc 配置: 这里将JAR包加入: JAR包是:/usr/local2/hadoop/share/hadoop 目录下:直接右边+以 ...

  4. 10.27night清北刷题班

    /* 枚举每个部分的总和,利用前缀和进行检验. 如果能分成4部分就一定能分成2部分,就筛了一边素数优化.清空数组!!! */ #include<bits/stdc++.h> #define ...

  5. composer查看安装情况

    composer install --no-progress --profile -vvv

  6. $Hdu1381\ Crazy\ Search$

    前置芝士 :string 的 基本用法 string s = "hello world" ; string tmp(s,0,5) ; cout << tmp <& ...

  7. video 能播放声音不能播放视频,黑屏

    与视频编码格式有关,mp4的视频编码有三种:MPEG4(DivX),MPEG4(Xvid),AVC(H264). 浏览器播放视频的支持有限,MP4格式的视频只支持h.264的视频: 视频编码: AVC ...

  8. ACM_Plants vs. Zombies(一元一次方程)

    Plants vs. Zombies Time Limit: 2000/1000ms (Java/Others) Problem Description: There is a zombie on y ...

  9. Xml学习笔记(3)利用递归解析Xml文档添加到TreeView中

    利用递归解析Xml文档添加到TreeView中 private void Form1_Load(object sender, EventArgs e) { XmlDocument doc = new ...

  10. Spring.Net学习笔记(4)-属性及构造器注入

    一.开发环境 操作系统:Win10 编译器:VS2013 .Net版本:.net framework4.5 二.涉及程序集 Spring.Core.dll:1.3.1 Common.Logging.d ...