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个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...
随机推荐
- Python基础 — NumPy
NumPy--简介 Numpy(Numerical Python的简称)是一个由多维数组对象和用于处理数组的例程集合组成的库. Numpy内部解除了Python的PIL(全局解释器锁),运算效率极 ...
- bzoj 1867: [Noi1999]钉子和小球【dp】
设f[i][j]为掉到f[i][j]时的概率然后分情况随便转移一下就好 主要是要手写分数比较麻烦 #include<iostream> #include<cstdio> usi ...
- GIT学习之路第一天 简介及其安装
本文参考廖雪峰老师的博客进行总结,完整学习请转廖雪峰博客 Git是什么? Git是目前世界上最先进的分布式版本控制系统(没有之一). Git有什么特点?简单来说就是:高端大气上档次! 那什么是版本控制 ...
- BFS POJ 3126 Prime Path
题目传送门 /* 题意:从一个数到另外一个数,每次改变一个数字,且每次是素数 BFS:先预处理1000到9999的素数,简单BFS一下.我没输出Impossible都AC,数据有点弱 */ /**** ...
- UC浏览器中,设置了position: fixed 的元素会遮挡z-index值更高的同辈元素
"UC浏览器中,设置了position: fixed 的元素会遮挡z-index值更高的同辈元素(非fixed)." 我们使用的artDialog弹窗中,在UC浏览器中,如果页面高 ...
- gauge自动化测试框架(二)
Gauge通过Markdown来描述行为,所以我还需先学习学习Markdown语法,看了一下,还好,十来分钟应该就可以搞定.具体学习见另一篇文章
- jQuery学习笔记(2)-选择器的使用
一.选择器是什么 有了jQuery的选择器,我们几乎可以获取页面上任意一个或一组对象 二.Dom对象和jQuery包装集 1.Dom对象 JavaScript中获取Dom对象的方式 <div i ...
- EasyUI系列学习(五)-Resizable(调整大小)
一.创建组件 1.使用标签创建可变大小的窗口 <div id="rBox" class="easyui-resizable" style="wi ...
- 关于Pyhton多线程同步队列的应用
''' 同步队列 put方法和task_done方法, queue有一个未完成任务数量num,put依次num+1, task依次num-1.任务都完成时任务结束. 1.创建一个 Queue.Queu ...
- Python多线程爬图&Scrapy框架爬图
一.背景 对于日常Python爬虫由于效率问题,本次测试使用多线程和Scrapy框架来实现抓取斗图啦表情.由于IO操作不使用CPU,对于IO密集(磁盘IO/网络IO/人机交互IO)型适合用多线程,对于 ...