题解:
区间加减维护gcd很麻烦,不过gcd可以差分,然后就变成单点加减了,用树链剖分维护一下原数列和差分数列即可,时间复杂度
O
(
n
log
3
n
)
O(n \log^3 n)
O(nlog3n)。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=2e5+50;
int n,q,a[N],top[N],dep[N],fa[N],sze[N],son[N],st[N],id[N],val[N],ind;
vector <int> e[N];
inline void dfs(int x,int f) {
fa[x]=f; dep[x]=dep[f]+1; sze[x]=1;
for(auto v:e[x]) if(v^f) {
dfs(v,x); sze[x]+=sze[v];
if(sze[son[x]]<sze[v]) son[x]=v;
}
}
inline void Dfs(int x,int f) {
st[x]=++ind; id[ind]=x; top[x]=f;
if(son[x]) Dfs(son[x],f);
for(auto v:e[x]) if(v^fa[x] && v^son[x]) Dfs(v,v);
}
inline int lca(int x,int y) {
while(top[x]^top[y]) (dep[top[x]]<dep[top[y]]) ? y=fa[top[y]] : (x=fa[top[x]]);
return (dep[x]<dep[y]) ? x : y;
}
inline bool in(int x,int y) {return st[x]<=st[y] && st[y]<st[x]+sze[x];}
inline int Abs(int x) {return (x>0) ? x : -x;}
inline void upt(int x) {val[x]=__gcd(Abs(val[x<<1]),Abs(val[x<<1|1]));}
inline void init(int k,int l,int r) {
if(l==r) {
val[k]=a[id[l]]-a[fa[id[l]]];
return;
} int mid=(l+r)>>1;
init(k<<1,l,mid);
init(k<<1|1,mid+1,r);
upt(k);
}
inline void inc(int k,int l,int r,int p,int v) {
if(l==r) {val[k]+=v; return;}
int mid=(l+r)>>1;
(p<=mid) ? inc(k<<1,l,mid,p,v) : inc(k<<1|1,mid+1,r,p,v);
upt(k);
}
inline int ask(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) {return Abs(val[k]);}
int mid=(l+r)>>1;
if(R<=mid) return ask(k<<1,l,mid,L,R);
else if(L>mid) return ask(k<<1|1,mid+1,r,L,R);
else return __gcd(ask(k<<1,l,mid,L,R),ask(k<<1|1,mid+1,r,L,R));
}
struct BIT {
int bit[N];
inline int ask(int i,int v=0) {for(;i;i-=i&(-i)) v+=bit[i]; return v;}
inline void inc(int i,int v) {for(;i<=n;i+=i&(-i)) bit[i]+=v;}
inline void inc(int l,int r,int v) {inc(l,v); inc(r+1,-v);}
} bit;
inline int ask_gcd(int f,int x) {
int v=(st[f]<st[x]) ? ask(1,1,n,st[f]+1,st[x]) : 0;
v=__gcd(v,bit.ask(st[f])+a[f]);
return v;
}
inline void group(int x,int f,int d) {
while(dep[x]>=dep[f]) {
int l=top[x];
if(dep[l]<dep[f]) l=f;
bit.inc(st[l],st[x],d);
if(son[x]) inc(1,1,n,st[son[x]],-d);
if(top[l]^l) inc(1,1,n,st[l],d);
x=fa[top[x]];
}
}
int main() {
n=rd();
for(int i=1;i<n;i++) {
int x=rd()+1, y=rd()+1;
e[x].push_back(y);
e[y].push_back(x);
} dfs(1,0); Dfs(1,1);
for(int i=1;i<=n;i++) a[i]=rd();
init(1,1,n);
q=rd();
for(int i=1;i<=q;i++) {
char ch=nc(); while(!isalpha(ch)) ch=nc();
int x=rd()+1, y=rd()+1, l=lca(x,y);
if(ch=='F') {
int v=0;
while(top[x]^top[l]) v=__gcd(v,ask_gcd(top[x],x)), x=fa[top[x]]; v=__gcd(v,ask_gcd(l,x));
while(top[y]^top[l]) v=__gcd(v,ask_gcd(top[y],y)), y=fa[top[y]]; v=__gcd(v,ask_gcd(l,y));
printf("%d\n",v);
} else {
int d=rd();
group(x,l,d);
group(y,l,d);
group(l,l,-d);
}
}
}
``