【算法】数学+线段树/树状数组

【题解】

首先三个操作可以理解为更相减损术或者辗转相除法(待证明),所以就是求区间gcd。

这题的问题在线段树维护gcd只能支持修改成一个数,不支持加一个数。

套路:gcd(a,b,c,d,e)=gcd(a-b,b-c,c-d,d-e,e),也就是所有数的gcd可以转化为所有差值和最后一个数的gcd

那么只需要查询区间差值gcd和一个数。

对于区间差值gcd查询,区间加数只会导致两个单位的差值变化,所以可以用线段树单点修改区间查询gcd。

对于一个数查询,就用树状数组维护区间加值和单点查询就行了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=;
struct tree{int l,r,g;}t[maxn*];
int a[maxn],c[maxn],n,m; int read()
{
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
void modify(int x,int k){for(int i=x;i<=n;i+=lowbit(i))c[i]+=k;}
int query(int x){int as=;for(int i=x;i>=;i-=lowbit(i))as+=c[i];return as;}//as给初值
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;
if(l==r)t[k].g=a[l]-a[l+];
else{
int mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
t[k].g=gcd(t[k<<].g,t[k<<|].g);
}
}
void add(int k,int x,int v){
if(t[k].l==t[k].r)t[k].g+=v;
else{
int mid=(t[k].l+t[k].r)>>;
if(x<=mid)add(k<<,x,v);
else add(k<<|,x,v);
t[k].g=gcd(t[k<<].g,t[k<<|].g);
}
}
int ask(int k,int l,int r){
if(l<=t[k].l&&t[k].r<=r)return t[k].g;
else{
int mid=(t[k].l+t[k].r)>>,x1=,x2=;
if(l<=mid)x1=ask(k<<,l,r);
if(r>mid)x2=ask(k<<|,l,r);
if(x1&&x2)return gcd(x1,x2);
if(x1)return x1;
return x2;
}
}
int ab(int x){return x>?x:-x;}
int main(){
n=read();m=read();
a[]=;
for(int i=;i<=n;i++)a[i]=read(),modify(i,a[i]-a[i-]);
a[n+]=;
build(,,n);
for(int i=;i<=m;i++){
int p=read(),l=read(),r=read();
if(l>r)swap(l,r);
if(p==){
if(l==r)printf("%d\n",query(r));
else printf("%d\n",ab(gcd(ask(,l,r-),query(r))));//gcd不怕0
}
else{
int v=read();
if(l>)add(,l-,-v);//注意边界!
add(,r,v);
modify(l,v);
if(r<n)modify(r+,-v);
}
}
return ;
}

最新文章

  1. MySQL SQL Mode及相关问题
  2. Visual Studio: How to change ipch path in Visual Studio 2010 (.sdf, *.opensdf, ...)
  3. php代码优化,mysql语句优化,面试需要用到的
  4. 百度定位并获取县区天气-XML+fragment+sqlite
  5. MyBatis中的特殊符号[20160713]
  6. java笔记--查看和修改线程的优先级
  7. 每日一笔记之3:QTconnect()
  8. 【usaco】patrol
  9. HTTP Post请求过程详解
  10. android139 360 黑名单 增删改查-数据库操作
  11. Beej网络socket编程指南
  12. [Data Structure] 红黑树( Red-Black Tree ) - 笔记
  13. Java虚拟机—垃圾回收算法(整理版)
  14. Log4net 配置文件组成
  15. 字符串拼接引发的BUG
  16. C++多线程同步技巧(四)--- 信号量
  17. Notes for &#39;Making elephants fly&#39;
  18. MergeKLists
  19. Entity Framework工具POCO Code First Generator的使用
  20. 简单实现textview文本每隔两秒就改变一次

热门文章

  1. Qt用委托绘制需要的图形的步骤
  2. 实现一个简单版的express
  3. 「个人训练」Radar Installation(POJ-1328)
  4. ubuntu 把软件源修改为国内源
  5. jmeter无法启动的解决办法
  6. JAVA虚拟机(一):内存区域
  7. python学习总结----内置函数及数据持久化
  8. sqlserver 找出字符第N次出现的位置
  9. 【UML】活动图介绍
  10. 服务追踪数据使用 RabbitMQ 进行采集 + 数据存储使用 Elasticsearch + 数据展示使用 Kibana