区间gcd (带修) 线段树

匿名 (未验证) 提交于 2019-12-02 23:59:01

题目链接:https://ac.nowcoder.com/acm/contest/1033/B

再次吐槽CH

区间gcd再加区间修改。

一般求gcd的时候辗转相除法。

gcd(x,y)=gcd(x,y-x)

那么可以把这个公式推到3个项。

gcd(x,y,z)=gcd(x,y-x,z-y)

可以看出来这是一个差分数列。

原数列为a[],差分数列为b[]。

这样就可以用线段树在b[]上单点修改,l加上d,r+1减去d。

再用树状数组维护出一个c[]数组,区间修改,单点查询a[]数组。

这样的话答案就是

gcd(a[l]+aks_c(l),ask_t(1,1,n,l+1,r))

就可以较小复杂度处理了。

代码如下:

#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=500001; int n,m; ll c[maxn],a[maxn],b[maxn]; struct node{     ll ans;     #define ans(x) t[x].ans }t[maxn<<2]; inline ll gcd(ll x,ll y){     return y ? gcd(y,x%y) : x; } inline void build(int p,int l,int r){     if(l==r){         ans(p)=b[l];return;     }     int mid=(l+r)>>1;     build(p<<1,l,mid);build(p<<1|1,mid+1,r);     ans(p)=gcd(ans(p<<1),ans(p<<1|1)); } inline void change(int p,int l,int r,int x,ll d){     if(l==r&&r==x){         ans(p)+=d;return;     }     int mid=(l+r)>>1;     if(x<=mid) change(p<<1,l,mid,x,d);     else change(p<<1|1,mid+1,r,x,d);     ans(p)=gcd(ans(p<<1),ans(p<<1|1)); } inline ll askt(int p,int l,int r,int x,int y){     if(x<=l&&r<=y)         return abs(ans(p));     int mid=(l+r)>>1;ll res=0;     if(x<=mid) res=gcd(res,askt(p<<1,l,mid,x,y));     if(y>mid) res=gcd(res,askt(p<<1|1,mid+1,r,x,y));     return abs(res); } inline void add(int x,ll y){     for(;x<=n;x+=(x&-x))         c[x]+=y; } inline ll askc(int x){     ll ans=0;     for(;x;x-=(x&-x))         ans+=c[x];     return ans; } int main() {     scanf("%d%d",&n,&m);     for(int i=1;i<=n;i++){         scanf("%lld",&a[i]);         b[i]=a[i]-a[i-1];     }     build(1,1,n);     for(int i=1;i<=m;i++){         char ch[2];scanf("%s",ch);         int l,r;scanf("%d%d",&l,&r);         if(ch[0]=='Q'){             printf("%lld\n",(ll)gcd(a[l]+askc(l),askt(1,1,n,l+1,r)));         }else{             ll d;scanf("%lld",&d);             change(1,1,n,l,d);             if(r<n) change(1,1,n,r+1,-d);             add(l,d);add(r+1,-d);         }     }     return 0; }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!