BZOJ 5028 小z的加油站
Time limit 10000 ms
Memory limit 262144 kB
OS Linux
感想
树上动态gcd的第二题也好了。
- [x] BZOJ 2257 [JSOI2009]瓶子和燃料
- [x] BZOJ 5028 小z的加油站
- [ ] CodeChef DGCD Dynamic GCD
解题思路
由上一题 [JSOI2009]瓶子和燃料 可知,这题这样子折腾就是在求区间最大公因数,这里还带上了区间加,所以需要另外一些性质——
参考了这篇博客。
众所周知,区间加作用到原序列上,相当于差分序列的两次单点修改(操作范围的右边顶着边界,那就是1次单点修改)。由更相减损可知,原序列总的gcd等于差分序列总的gcd,即差分一下gcd不变(此时求gcd的函数要注意将小于零的参数换成其绝对值进行计算,因为更相减损是大的减小的)。
\[\gcd\left(a_{1}, a_{2}, a_{3}, \dots, a_{n-2}, a_{n-1}, a_{n}\right)
\]\[=\gcd \left(a_{1}, a_{2}-a_{1}, a_{3}-a_{2}, \ldots a_{n-1}-a_{n-2}, a_{n}-a_{n-1}\right)
\]
设\(a_0=0\),\(d_i=a_i-a_{i-1}\)(差分数组),于是把上式推广到其他区间——
\[\gcd\left(a_{l}, a_{l+1}, a_{l+2}, \dots, a_{r-2}, a_{r-1}, a_{r}\right)
\]\[=\gcd\left( a_{l} , \gcd (d_{l+1}, d_{l+2}, \ldots, d_{r})\right)
\]\[=\gcd\left(\sum_{i=1}^{l} d_{l} , \gcd \left(d_{l+1}, d_{l+2}, \ldots, d_{r}\right)\right)
\]
又因为gcd满足区间加法,于是,我们就可以用线段树维护差分序列的区间和、gcd。
顺便,Hint里出现的那个\(L>R\)意思应该不是说数据有锅,而是说,当查询的区间长度为1时,要注意特判。
观察上式——$$\gcd\left(\sum_{i=1}^{l} d_{l} , \gcd \left(d_{l+1}, d_{l+2}, \ldots, d_{r}\right)\right)$$
对于这一项$$\gcd \left(d_{l+1}, d_{l+2}, \ldots, d_{r}\right)$$
当\(l=r\),即查询区间长度为1时,会出现\(l+1>r\)的情况,此时这一项应该直接返回0,以防止干扰结果。或者在其他地方特判一下也行。
源代码
#include<stdio.h>
const int MAXN=1e5+5;
long long gcd(long long x,long long y)
{
if(x<0) x=-x;
if(y<0) y=-y;
return y==0?x:gcd(y,x%y);
}//更相减损是大的减小的
int n,m;
long long d[MAXN];//差分数组
struct Segtree{
long long g,sum;
}t[MAXN<<2];//维护差分数组的线段树
void pushup(int x)
{
t[x].g=gcd(t[x<<1].g,t[x<<1|1].g);
t[x].sum=t[x<<1].sum+t[x<<1|1].sum;
}
void build(int x,int l,int r)
{
if(l==r)
{
t[x].g=t[x].sum=d[l];
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
void update(int x,int l,int r,int pos,int k)//pos处增加k
{
if(l==r)
{
t[x].sum+=k;
t[x].g+=k;
return;
}
int mid=l+r>>1;
if(pos<=mid) update(x<<1,l,mid,pos,k);
else update(x<<1|1,mid+1,r,pos,k);
pushup(x);
}
long long quesum(int x,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)
return t[x].sum;
long long ans=0;
int mid=l+r>>1;
if(ql<=mid) ans+=quesum(x<<1,l,mid,ql,qr);
if(qr>mid) ans+=quesum(x<<1|1,mid+1,r,ql,qr);
return ans;
}
long long quegcd(int x,int l,int r,int ql,int qr)
{
if(ql>qr) return 0;//特判这个
if(ql<=l&&r<=qr)
return t[x].g;
long long ans;
int mid=l+r>>1;
if(qr<=mid) ans=quegcd(x<<1,l,mid,ql,qr);
else if(ql>mid) ans=quegcd(x<<1|1,mid+1,r,ql,qr);
else ans=gcd(quegcd(x<<1,l,mid,ql,qr),quegcd(x<<1|1,mid+1,r,ql,qr));
return ans;
}
inline long long opt1(int l,int r)//区间询问gcd
{
return gcd(quesum(1,1,n,1,l),quegcd(1,1,n,l+1,r));
}
void opt2(int l,int r,int k)//区间增加k
{
update(1,1,n,l,k);
if(r<n) update(1,1,n,r+1,-k);
}
int main()
{
//freopen("test.in","r",stdin);
scanf("%d%d",&n,&m);
d[0]=0;
for(int i=1;i<=n;i++)
scanf("%lld",d+i);
for(int i=n;i>1;i--)
d[i]-=d[i-1];
build(1,1,n);
while(m--)
{
int opt,l,r,k;
scanf("%d%d%d",&opt,&l,&r);
if(opt==1)
{
printf("%lld\n",opt1(l,r));
}
else
{
scanf("%d",&k);
opt2(l,r,k);
}
}
return 0;
}
BZOJ 5028 小z的加油站的更多相关文章
- bzoj 5028: 小Z的加油店——带修改的区间gcd
Description 小Z经营一家加油店.小Z加油的方式非常奇怪.他有一排瓶子,每个瓶子有一个容量vi.每次别人来加油,他会让 别人选连续一段的瓶子.他可以用这些瓶子装汽油,但他只有三种操作: 1. ...
- BZOJ 5028 小Z的加油店
[题解] 本题要求求出区间内的各个元素通过加减之后能够得出的最小的数,那么根据裴蜀定理可知答案就是区间内各个元素的最大公约数. 那么本题题意化简成了维护一个序列,支持区间加上某个数以及查询区间元素的最 ...
- bzoj 4031: 小Z的房间 矩阵树定理
bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...
- BZOJ 2038 小z的袜子 & 莫队算法(不就是个暴力么..)
题意: 给一段序列,询问一个区间,求出区间中.....woc! 贴原题! 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过 ...
- bzoj 2308 小Z的袜子(莫队算法)
小Z的袜子 [题目链接]小Z的袜子 [题目类型]莫队算法 &题解: 莫队算法第一题吧,建议先看这个理解算法,之后在参考这个就可以写出简洁的代码 我的比第2个少了一次sort,他的跑了1600m ...
- BZOJ 2038 小Z的袜子(hose) 莫队算法模板题
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2038 题目大意: 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中 ...
- BZOJ 2038 小z的袜子(莫队)
Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜 ...
- bzoj 2038 小Z的袜子(hose)(莫队算法)
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 11542 Solved: 5166[Sub ...
- (原创)BZOJ 2038 小Z的袜子(hose) 莫队入门题+分块
I - 小Z的袜子(hose) 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z ...
随机推荐
- python 并发编程 多线程 GIL全局解释器锁基本概念
首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念. 就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码. ...
- mysql标准规范
一.基础规范 表存储引擎必须使用InnoDB 表字符集默认使用utf8,必要时候使用utf8mb4 解读: (1)通用,无乱码风险,汉字3字节,英文1字节 (2)utf8mb4是utf8的超集,有存储 ...
- POJ 2253 Frogger(dijkstra 最短路
POJ 2253 Frogger Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fion ...
- Head First PHP&MySQl第三章代码
addemail.html <!DOCTYPE html> <html lang="cn"> <head> <meta charset=& ...
- day 14 装饰器
装饰器:装饰,装修,房子就可以住,如果装修,不影响你住,而且体验更加,让你生活中增加了很多功能:洗澡,看电视,沙发.器:工具.开放封闭原则:开放:对代码的拓展开放的, 更新地图,加新枪,等等.封闭:对 ...
- qt在tableview中绘制图片
void ItemModelDeletage::paint(QPainter *painter, const QStyleOptionViewItem &option, const QMode ...
- SVM支持向量机(2)
零.各种概念 1.硬间隔最大化 2.硬间隔支持向量机 3.线性支持向量机 软间隔最大化 软间隔支持向量机 4.非线性支持向量机 核函数kernel function 一.理解支持向量机SVM的原理 ...
- mariadb数据库简介
mariadb(默认端口3306) 什么是数据库? 白话:用来存放数据的仓库,这个仓库只不过是按照一定的数据结构来组织. 数据库模型分为三种: 层次式数据库 网络式数据库 关系型数据库和非关系数据库 ...
- (转) windows 下ORA-12514:TNS 监听问题
在使用Orcale数据库的时候不知道各位是否遇到过如图的监听问题(或者显示类似的问题),以下方法就是来解决这样的问题的. 首先右击计算机,选择管理.选择左侧栏的服务与应用程序,右侧栏选服务. ...
- 转载:PHP编程规范
PHP-FIG 在说啥是PSR-[0-4]规范的之前,我觉得我们有必要说下它的发明者和规范者:PHP-FIG,它的网站是:www.php-fig.org.就是这个联盟组织发明和创造了PSR-[0-4] ...