区间最大公约数

给定长度为N的数列A,以及M条指令,指令为一下两种之一:

1. C L R d 表示把A[L],A[L+1].....A[R]都加上d

2. Q L R 表示查询 A[L]......A[R]的最大公约数

对于每个询问输出一个答案;

 

这个题算是经典的线段树的问题了,因为:区间修改+区间查询

这道题好就好在可以用差分的思维来代替懒标记

这样区间修改就变成了单点修改,在A[L]+d,A[R+1]-d

 

之所以可以用差分来代替是因为(a,b,c) = (a,b-a,c-b)

以此类推我们可以得到,只要我们得知a的值就可以递推出b-a,c-b的值,所以我们构造b[n]来存储差分

复制代码
 1 # include<iostream>
 2 # include<algorithm>
 3 # include<cstring>
 4 # define int long long
 5 # define endl "\n"
 6 using namespace std;
 7 const int N = 5e5+10;
 8 struct node{
 9     int l,r;
10     int sum,d;
11 }tr[N*4];/*l,r区间范围
        sum差分数组
        d区间最大公约数
        
*/
12 int w[N],n,m; 13 14 int gcd(int a,int b){ 15 return b?gcd(b,a%b):a; 16 } 17 18 void pushup(node &u,node &l,node &r){ 19 u.sum = l.sum+r.sum; 20 u.d = gcd(l.d,r.d); 21 } 22 23 void pushup(int u){ 24 pushup(tr[u],tr[u<<1],tr[u<<1|1]); 25 } 26 27 void build(int u,int l,int r){ 28 if(l == r){ 29 int b = w[r]-w[r-1];/*差分*/ 30 tr[u] = {l,r,b,b}; 31 return; 32 } 33 tr[u] = {l,r}; 34 int mid = l+r>>1; 35 build(u<<1,l,mid),build(u<<1|1,mid+1,r); 36 pushup(u);/*向上更新*/ 37 } 38 39 void modify(int u,int x,int v){ 40 if(tr[u].l == x&&tr[u].r==x){ 41 int b = tr[u].sum+v; 42 tr[u]={x,x,b,b}; 43 return; 44 } 45 int mid = tr[u].l+tr[u].r>>1; 46 if(x<=mid){ 47 modify(u<<1,x,v); 48 } 49 else{ 50 modify(u<<1|1,x,v); 51 } 52 pushup(u); 53 } 54 55 node query(int u,int l,int r){ 56 if(tr[u].l>=l && tr[u].r<=r){ 57 return tr[u]; 58 } 59 int mid = tr[u].l+tr[u].r>>1; 60 if(r<=mid) return query(u<<1,l,r); 61 else if(l>mid) return query(u<<1|1,l,r); 62 else{ 63 auto left = query(u<<1,l,r); 64 auto right = query(u<<1|1,l,r); 65 node res; 66 pushup(res,left,right); 67 return res; 68 } 69 } 70 signed main(){ 71 ios::sync_with_stdio(false); 72 cin.tie(0); 73 cout.tie(0); 74 cin>>n>>m; 75 for(int i = 1; i <= n;++i) cin>>w[i]; 76 build(1,1,n); 77 78 int l,r,d; 79 char op[2]; 80 while(m--){ 81 cin>>op>>l>>r; 82 if(*op == 'Q'){ 83 auto left = query(1,1,l); 84 node right = {0,0,0,0}; 85 if(l+1<=r) right = query(1,l+1,r); 86 cout<<abs(gcd(left.sum,right.d))<<endl; 87 } 88 else{ 89 cin>>d; 90 modify(1,l,d); 91 if(r+1<=n) modify(1,r+1,-d); 92 } 93 } 94 95 96 return 0; 97 }
复制代码

所以最后我们想要得到的答案就是gcd(a1,gcd(b-a,c-b,d-c....))

posted @   empty_y  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示