题目描述

给出 $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. BZOJ4034_树上操作_KEY

    题目传送门 这道题可以树链剖分+线段树. 其他操作模板,第二个操作只需要将x~x+size[x]-1区间加值即可. code: #include <cstdio> #include < ...

  2. 服务端调用接口API利器之HttpClient

    前言 之前有介绍过HttpClient作为爬虫的简单使用,那么今天在简单的介绍一下它的另一个用途:在服务端调用接口API进行交互.之所以整理这个呢,是因为前几天在测试云之家待办消息接口的时候,有使用云 ...

  3. 使用Python的BeautifulSoup 类库采集网页内容

    BeautifulSoup 一个分析.处理DOM树的类库.可以做网络爬虫.模块简称bs4. 安装类库 easy_install beautifulsoup4 pip install beautiful ...

  4. CI框架浅析(一)

            CodeIgniter 是一个小巧但功能强大的 PHP 框架,作为一个简单而“优雅”的工具包,它可以为开发者们建立功能完善的 Web 应用程序.本人使用CI框架有一段时间了,现在决定把 ...

  5. 准备正式开始学习C++,先发点牢骚

    由于职业关系,经常使用AutoCAD之类绘图软件,但这些软件平台的功能,对专业的应用细节来说,并不能全都照顾到,需要一些二次开发,提升一些个性化操作的效率.软件本身也大多提供了开发软件包,AutoCA ...

  6. PHP:Iterator(迭代器)接口和生成器

    迭代器 可在内部迭代自己的外部迭代器或类的接口.详情:http://php.net/manual/zh/class.iterator.php 接口摘要 Iterator extends Travers ...

  7. 从武侠中的兵器看待数据访问工具——Hibernate Spring.Data Mybatis

    <泪痕剑>第31集,卓爷大谈自己的兵器,我从中摘录,觉得非常受用. “你错了,我们和武器之间的关系,就好像选择情人一样,不管是否擅长,都要用感情. 我少年时候用刀,青年时候仍用刀,不知道用 ...

  8. 高可用Kubernetes集群-4. kubectl客户端工具

    六.部署kubectl客户端工具 1. 下载 [root@kubenode1 ~]# cd /usr/local/src/ [root@kubenode1 src]# wget https://sto ...

  9. 【BUG】12小时制和24小时制获取当天零点问题

    [BUG]12小时制和24小时制获取当天零点问题 最近在写定时服务的时候,要获取当天的零点这个时间,但是是这样获取的 DateTime dt = DateTime.Parse(DateTime.Now ...

  10. 【python 3.6】如何将list存入txt后,再读出list

    今天遇到一个需求,就是将一个list文件读取后,存入一个txt配置文件.存入时,发现list文件无法直接存入,必须转为str模式. 但在读取txt时,就无法恢复成list类型来读取了(准确地说,即使强 ...