题目描述

给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量。每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满。$m$ 次操作,每次给 $[l,r]$ 内的瓶子容量增加 $x$ ,或询问使用 $[l,r]$ 内瓶子能够凑出的最小体积。

输入

第一行包括两个数字:瓶子数n,事件数m。
第二行包含n个整数,表示每个瓶子的容量vi。
接下来m行,每行先有三个整数fi li ri。
若fi=1表示询问li到ri他最少能倒腾出的汽油量最少是多少?
若fi=2 再读入一个整数x。表示他将li到ri的瓶子容量都增加了x。
1 <= n,m <= 10^5 , 1<=li<=ri<=n , 1<=初始容量,增加的容量<=1000

输出

对于每个询问输出对应的答案

样例输入

3 4
2 3 4
1 1 3
2 2 2 1
1 1 3
1 2 3

样例输出

1
2
4


题解

扩展裴蜀定理+差分+线段树

【bzoj2257】瓶子和燃料 的结论,答案为区间 $\gcd$ 。

那么问题转化为:区间加、区间求 $\gcd$ 。

直接解决这个问题比较困难。我们知道,$\gcd(a,b,c)=\gcd(a,b-a,c-b)$ ,即区间 $\gcd$ 等于 $l$ 位置的数与 $[l+1,r]$ 的差分数组的 $\gcd$ 。而区间加在差分数组上表现为单点加减,较容易维护。

因此对原数组求差分数组,修改时在差分数组上进行单点加减,查询时查询差分数组的前缀和及区间 $\gcd$ ,最大公约数即为答案。

时间复杂度 $O(n\log n)$ (求 $\gcd$ 的 $\log$ 在线段树pushup的过程中均摊掉了,因此只有一个 $\log$ )

#include <cstdio>
#include <algorithm>
#define N 100010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
int a[N] , sum[N << 2] , val[N << 2];
inline int gcd(int a , int b)
{
int t;
while(b) t = a , a = b , b = t % b;
return a;
}
inline void pushup(int x)
{
sum[x] = sum[x << 1] + sum[x << 1 | 1] , val[x] = gcd(val[x << 1] , val[x << 1 | 1]);
}
void build(int l , int r , int x)
{
if(l == r)
{
sum[x] = val[x] = a[l] - a[l - 1];
return;
}
int mid = (l + r) >> 1;
build(lson) , build(rson);
pushup(x);
}
void update(int p , int a , int l , int r , int x)
{
if(p > r) return;
if(l == r)
{
sum[x] += a , val[x] += a;
return;
}
int mid = (l + r) >> 1;
if(p <= mid) update(p , a , lson);
else update(p , a , rson);
pushup(x);
}
int qsum(int p , int l , int r , int x)
{
if(l == r) return sum[x];
int mid = (l + r) >> 1;
if(p <= mid) return qsum(p , lson);
else return qsum(p , rson) + sum[x << 1];
}
int qval(int b , int e , int l , int r , int x)
{
if(b > e) return 0;
if(b <= l && r <= e) return val[x];
int mid = (l + r) >> 1 , ans = 0;
if(b <= mid) ans = gcd(ans , qval(b , e , lson));
if(e > mid) ans = gcd(ans , qval(b , e , rson));
return ans;
}
int main()
{
int n , m , i , opt, l , r , x;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
build(1 , n , 1);
while(m -- )
{
scanf("%d%d%d" , &opt , &l , &r);
if(opt == 1) printf("%d\n" , abs(gcd(qsum(l , 1 , n , 1) , qval(l + 1 , r , 1 , n , 1))));
else scanf("%d" , &x) , update(l , x , 1 , n , 1) , update(r + 1 , -x , 1 , n , 1);
}
return 0;
}

【bzoj5028】小Z的加油店 扩展裴蜀定理+差分+线段树的更多相关文章

  1. [BZOJ5028]小Z的加油店

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

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

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

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

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

  4. 【bzoj2257】[Jsoi2009]瓶子和燃料 扩展裴蜀定理+STL-map

    题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.从中选出 $k$ 个瓶子,使得能够通过这 $k$ 个瓶子凑出 ...

  5. 【bzoj1441】Min 扩展裴蜀定理

    题目描述 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小 输入 第一行给出数字N,代表有N个数 下面一行给出N个数 输出 S ...

  6. BZOJ 5028 小Z的加油店

    [题解] 本题要求求出区间内的各个元素通过加减之后能够得出的最小的数,那么根据裴蜀定理可知答案就是区间内各个元素的最大公约数. 那么本题题意化简成了维护一个序列,支持区间加上某个数以及查询区间元素的最 ...

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

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

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

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

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

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

随机推荐

  1. How to bind a Command on a ContextMenu within a DataTemplate using MVVM

    Since the Popuup control has it's separate visual tree, you cannot use find ancestor to find the Gri ...

  2. WPF 带水印的密码输入框实现

    原文:WPF 带水印的密码输入框实现 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/article/details/835055 ...

  3. 【BZOJ3197】[SDOI2013]刺客信条

    [BZOJ3197][SDOI2013]刺客信条 题面 bzoj 洛谷 题解 关于树的同构,有一个非常好的性质: 把树的重心抠出来,那么会出现两种情况: 1.有一个重心,那么我们直接把这个重心作为树的 ...

  4. httpclient在获取response的entity时报异常

    httpClient报异常:Premature end of chunk coded message body: closing chunk expected 首先这个异常提示直译过来就是:被编码信息 ...

  5. C++ OI图论 学习笔记(初步完结)

    矩阵图 使用矩阵图来存储有向图和无向图的信息,用无穷大表示两点之间不连通,用两点之间的距离来表示连通.无向图的矩阵图是关于主对角线对称的. 如图所示: 使用dfs和bfs对矩阵图进行遍历 多源最短路径 ...

  6. 探究linux设备驱动模型之——platform虚拟总线(一)

    说在前面的话 :      设备驱动模型系列的文章主要依据的内核版本是2.6.32的,因为我装的Linux系统差不多就是这个版本的(实际上我用的fedora 14的内核版本是2.6.35.13的.) ...

  7. 05-Docker架构详解

    Docker 的核心组件包括: Docker 客户端 - Client Docker 服务器 - Docker daemon Docker 镜像 - Image Registry Docker 容器 ...

  8. flexbox的应用

    2009年,display: box 就已经出现,但是直到IE11的发布,全部的主流浏览器才统一支持新的用法display: flex. 这里只说应用,浏览器的兼容处理会附在文章的末尾. 起步 在现代 ...

  9. Struts2(一.基本介绍,环境搭建及需求分析)

    Struts2框架开发 前言 开发工具:eclipse struts1:老项目使用较多,维护时需要用到 struts2:新项目使用较多 一.特点 1. 无侵入式设计 struts2 与 struts ...

  10. “错误: 编码GBK的不可映射字符” 的解决方案

    命令行下,用javac命令编译java程序时,如果文档的编码为“utf-8”,并且含有中文字符时,会出现乱码现象,编译通过不了.如图: 解决方案:编译时指定编码方式,防止乱码.如下: