Soratosorato

Interval GCD 题解

Sorato·2024-03-09 17:32·54 次阅读

Interval GCD 题解

题目描述

给定一个长度为 n 的数组 a,以及 m 条指令 (n5×105,m105),每条指令可能是以下两种之一:

C l r d”,表示把 a[l],a[l+1],,a[r] 都加上 d

Q l r”,表示询问 a[l],a[l+1],,a[r]gcd


Solve

1.引理#

更相减损术 gcd(a,b)=gcd(a,ab) 可利用数学归纳法扩展至 gcd(a1,a2,,an)=gcd(a1,a2a1,a3a2,,anan1)

2.思路#

考虑利用差分将区间修改转化为单点修改,用线段树维护区间 gcd,然后用树状数组维护前缀和以求出 ai 的真实值(也可以用线段树维护)。

3.Code#

Copy
#include<bits/stdc++.h> #pragma GCC optimize(1) #pragma GCC optimize(2) #pragma GCC optimize(3,"Ofast","inline") using namespace std; #define int long long inline int read() { short f=1; int x=0; char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } struct seg { int dat,l,r; #define mid (t[p].l+t[p].r>>1) #define ls (p<<1) #define rs (p<<1|1) #define len(p) (t[p].r-t[p].l+1) }t[2000010]; int gcd(int x,int y) { x=abs(x);y=abs(y);//考虑负数 if(x<y) swap(x,y); if(!y) return x;//在query中res=0,即y=0,此时直接返回x return x%y?gcd(y,x%y):y; } int n,m,a[500010],c[500010],l,r,d; char op; inline void upd(int p) { t[p].dat=gcd(t[ls].dat,t[rs].dat); } void build(int p,int l,int r) { t[p].l=l;t[p].r=r; if(l==r) { t[p].dat=a[l]-a[l-1]; return; } build(ls,l,mid); build(rs,-~mid,r); upd(p); } void change(int p,int pos,int d) { if(t[p].l==t[p].r) { t[p].dat+=d; return; } if(mid>=pos) change(ls,pos,d); if(mid<pos) change(rs,pos,d); upd(p); } int query(int p,int l,int r) { if(t[p].l>=l&&t[p].r<=r) return t[p].dat; int res=0; if(mid>=l) res=gcd(res,query(ls,l,r)); if(mid<r) res=gcd(res,query(rs,l,r)); return res; } inline void add(int x,int y) {for(;x<=n;x+=x&-x) c[x]+=y;} inline int ask(int x) {int res=0;for(;x;x-=x&-x) res+=c[x];return res;} void print(int p) { if(t[p].l==t[p].r) { printf("%lld ",t[p].dat); return; } print(ls);print(rs); } signed main() { freopen("test.in","r",stdin); freopen("test.out","w",stdout); n=read();m=read(); for(int i=1;i<=n;i=-~i) a[i]=read(),add(i,a[i]-a[i-1]); build(1,1,n); for(int i=1;i<=m;i=-~i) { cin>>op; l=read();r=read(); if(op=='Q') printf("%lld\n",gcd(ask(l)/*a[l]的真实值*/,query(1,-~l,r)/*gcd(a[l+1]~a[r])*/)); else { d=read();add(l,d);add(-~r,-d), change(1,l,d); if(r<n) change(1,-~r,-d);//注意r=n的情况,change会越界导致bug } } return 0; }
posted @   Sorato  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示
目录