C27 线段树 区间最大公约数_哔哩哔哩_bilibili
CH4302 Interval GCD
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ls u<<1
#define rs u<<1|1
const int N=500010;
typedef long long LL;
int n,m; LL a[N],b[N];
struct Tree{ //线段树
int l,r;
LL sum,d; //差分序列的区间和,最大公约数
}tr[N*4];
LL gcd(LL a,LL b){
return b ? gcd(b,a%b) : a;
}
void pushup(Tree &u,Tree l,Tree r){
u.sum=l.sum+r.sum;
u.d=gcd(l.d,r.d);
}
void build(int u,int l,int r){ //建树
tr[u]={l,r,b[l],b[l]};
if(l==r) return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(tr[u],tr[ls],tr[rs]);
}
void change(int u,int x,LL v){ //点修
if(tr[u].l==tr[u].r){
tr[u].sum+=v; tr[u].d+=v;
return;
}
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid) change(ls,x,v);
else change(rs,x,v);
pushup(tr[u],tr[ls],tr[rs]);
}
Tree query(int u,int l,int r){ //区查
if(l<=tr[u].l && tr[u].r<=r) return tr[u];
int mid=tr[u].l+tr[u].r>>1;
if(r<=mid) return query(ls,l,r);
if(l>mid) return query(rs,l,r);
Tree T; //开一个临时节点,存储拼凑结果
pushup(T,query(ls,l,r),query(rs,l,r));
return T;
}
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);
while(m --){
char c[1]; int l,r; scanf("%s%d%d",c,&l,&r);
if(*c=='C'){
LL v; scanf("%lld",&v);
change(1,l,v);
if(r+1<=n) change(1,r+1,-v); //r=n时,越界
}
else{
Tree L, R={0,0,0,0};
L=query(1,1,l); //a[l]=sum(b[1~l])
if(l+1<=r) R=query(1,l+1,r);//b[l+1~r]的gcd
printf("%lld\n",abs(gcd(L.sum, R.d)));
}
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ls u<<1
#define rs u<<1|1
const int N=500010;
typedef long long LL;
int n,m; LL a[N],b[N];
struct Tree{ //线段树
int l,r;
LL sum,d; //差分序列的区间和,最大公约数
}tr[N*4];
LL gcd(LL a,LL b){
return b ? gcd(b,a%b) : a;
}
void pushup(Tree &u,Tree l,Tree r){
u.sum=l.sum+r.sum;
u.d=gcd(l.d,r.d);
}
void build(int u,int l,int r){ //建树
tr[u]={l,r,b[l],b[l]};
if(l==r) return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(tr[u],tr[ls],tr[rs]);
}
void change(int u,int x,LL v){ //点修
if(tr[u].l==tr[u].r){
tr[u].sum+=v; tr[u].d+=v;
return;
}
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid) change(ls,x,v);
else change(rs,x,v);
pushup(tr[u],tr[ls],tr[rs]);
}
Tree query(int u,int l,int r){ //区查
if(l<=tr[u].l && tr[u].r<=r) return tr[u];
int mid=tr[u].l+tr[u].r>>1;
Tree T,T1={0,0,0,0},T2={0,0,0,0};
if(l<=mid) T1=query(ls,l,r);
if(r>mid) T2=query(rs,l,r);
pushup(T,T1,T2);
return T;
}
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+1);
while(m --){
char c[1]; int l,r; scanf("%s%d%d",c,&l,&r);
if(*c=='C'){
LL v; scanf("%lld",&v);
change(1,l,v);
change(1,r+1,-v);
}
else{
Tree L, R={0,0,0,0};
L=query(1,1,l); //a[l]=sum(b[1~l])
R=query(1,l+1,r); //b[l+1~r]的gcd
printf("%lld\n",abs(gcd(L.sum, R.d)));
}
}
return 0;
}
Luogu P1890 gcd区间