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个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...
随机推荐
- HTML5来了,7个混合式移动开发框架
在这个时间开始学习移动开发真是最好不过了,每个人应该都有一些移动应用的创意,而且你并不需要任何的原生应用编程经验,你只需要一些HTML的相关知识,懂一些CSS和JavaScript就够了.如果你总听别 ...
- Maven之项目搭建与第一个helloworld(多图)
这次记录第一个搭建一个maven的helloworld的过程. 转载 1.搭建web工程肯定得new 一个 maven工程,假如project中没有直接看到maven工程,那么选择Other,然后在W ...
- 51nod 1166 大数开平方
1166 大数开平方 基准时间限制:4 秒 空间限制:131072 KB 分值: 320 难度:7级算法题 收藏 关注 给出一个大整数N,求不大于N的平方根的最大整数.例如:N = 8,2 * 2 ...
- 【转】Java实现将文件或者文件夹压缩成zip
转自:https://www.cnblogs.com/zeng1994/p/7862288.html package com.guo.utils; import java.io.*; import j ...
- AndroidStudio3.0 Canary 8注解报错Annotation processors must be explicitly declared now.
体验最新版AndroidStudio3. Canary 8的时候,发现之前项目的butter knife报错,用到注解的应该都会报错 Error:Execution failed for task ' ...
- Python学习日记之文件读取操作
Python内置了文件读写的函数open,read 用法示例: open('/home/root/files.txt ') 在打开文件后,操作完成后可以使用close()关闭文件,但比较好的文件读写方 ...
- 解决安装androidstudio无法查看源代码的问题
如果androidstudio的sdk是自己导入的,则可能会有查看不了源代码的原因.原因是默认目录中没有这个api的源代码. 1.先在C:\Users\xxx\.AndroidStudio2.3\co ...
- [Windows Server 2012] 初识Windows Server 2012
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:初次见识Win ...
- Spring+Spring MVC+Hibernate增查(使用注解)
使用Spring+Spring MVC+Hibernate做增删改查开发效率真的很高.使用Hibernate简化了JDBC连接数据库的的重复性代码.下面根据自己做的一个简单的增加和查询,把一些难点分析 ...
- Linux基础之操作系统
一.什么是操作系统 简单来说,操作系统就是一个协调.管理和控制计算机硬件资源和软件资源的控制程序. 二.操作系统存在的意义 究根结底,我们日常对计算机的管理是对计算机硬件的管理.经过近百年的时间,现代 ...