用更相减损术的思想化为维护差分就很容易做了,lct与树链剖分均可,边界要注意,中间直接弄成开区间
codechef常数也卡得很厉害...
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
int a[200000],b[200000],gcc[200000],ad[200000],rt[200000],l[200000],r[200000],d[200000],st[200000];
int n,q,ans,next[500000],sora[500000],tail[500000],ss;
inline void link(int x,int y)
{
++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y;
++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x;
}
void bfs(int s)
{
memset(d,127,sizeof(d));
int h,r=h=0;
st[r=1]=s,d[s]=0,b[s]=gcc[s]=a[s];
for (;h<r;) {
int ne=st[++h],na;
for (int i=ne;next[i];) {
i=next[i],na=sora[i];
if (d[ne]+1<d[na]) {
d[na]=d[ne]+1;
st[++r]=na;
rt[na]=ne,b[na]=a[na]-a[ne],gcc[na]=abs(b[na]);
}
}
}
}
inline int gcd(int a,int b)
{
a=abs(a),b=abs(b);
if (!a) return b;
if (!b) return a;
for (;a%b;) {
int t=a%b;
a=b;
b=t;
}
return b;
}
inline void updata(int x)
{
gcc[x]=gcd(gcc[l[x]],gcc[r[x]]);
gcc[x]=gcd(gcc[x],b[x]);
}
inline void add(int x,int w)
{
if (!x) return ;
a[x]+=w;
ad[x]+=w;
}
inline void pushdown(int x)
{
if (!x) return ;
if (ad[x]) add(l[x],ad[x]),add(r[x],ad[x]);
ad[x]=0;
}
inline void left(int x)
{
int y=rt[x],z=rt[y];
r[y]=l[x],rt[l[x]]=y;updata(y);
l[x]=y,rt[y]=x;
if (l[z]==y) l[z]=x;else if (r[z]==y) r[z]=x;rt[x]=z;
}
inline void right(int x)
{
int y=rt[x],z=rt[y];
l[y]=r[x],rt[r[x]]=y;updata(y);
r[x]=y,rt[y]=x;
if (l[z]==y) l[z]=x;else if (r[z]==y) r[z]=x;rt[x]=z;
}
inline void splay(int x)
{
pushdown(x);
for (;l[rt[x]]==x || r[rt[x]]==x;) {
int y=rt[x],z=rt[y];
if (l[z]==y || r[z]==y) pushdown(z);pushdown(y);pushdown(x);
if (l[y]==x) {
if (l[z]==y) right(y);
right(x);
}
else {
if (r[z]==y) left(y);
left(x);
}
}
updata(x);
}
inline void access(int x)
{
int xx=x;
splay(x);
l[x]=0,updata(x);
for (;rt[x];) {
int y=rt[x],z;
splay(y);
for (z=x;r[z];z=r[z]) ;
splay(z);
b[z]=a[z]-a[y],updata(z);
l[y]=z,updata(y);
x=y;
}
splay(xx);
}
void origin()
{
ss=n;
for (int i=1;i<=n;i++) tail[i]=i;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d\n",&n);
origin();
for (int i=1;i<=n-1;i++) {
int x,y;
scanf("%d%d\n",&x,&y);
x++,y++;
link(x,y);
}
for (int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("\n");
bfs(1);
cin>>q;
scanf("\n");
for (int i=1;i<=q;i++) {
int root,x,y,z;
char ch;
scanf("%c",&ch);
//printf("%d\n",clock());
if ('C'==ch) {
scanf("%d%d%d\n",&x,&y,&z);x++,y++;
if (!z) continue;
if (x==y) {
splay(x);
a[x]+=z,b[x]+=z;updata(x);
continue;
}
access(x),access(y);
splay(x),root=rt[x];
if (!root) root=x;
access(root);
if (root!=x) splay(x),add(x,z);
if (root!=y) splay(y),add(y,z);
a[root]+=z,b[root]+=z,updata(root);
}
else {
scanf("%d%d\n",&x,&y);x++,y++;
if (x==y) {
splay(x);
printf("%d\n",a[x]);
continue;
}
access(x),access(y);
splay(x),root=rt[x];
if (!root) root=x;
access(root);
ans=0;
if (root!=x) splay(x),ans=gcd(ans,gcc[x]),ans=gcd(ans,a[x]);
if (root!=y) splay(y),ans=gcd(ans,gcc[y]),ans=gcd(ans,a[y]);
ans=gcd(ans,a[root]);
printf("%d\n",ans);
}
}
//if (clock()>1000) printf("1\n");
//printf("%d\n",clock());
return 0;
}