Dynamic GCD

All submissions for this problem are available.
You're given a tree on N vertices. Each vertex has a positive integer written on it, number on the ith vertex being vi. Your program must process two types of queries :

1. Find query represented by F u v   : Find out gcd of all numbers on the unique path between vertices u and v in the tree (both inclusive).
2. Change query represented by C u v d : Add d to the number written on all vertices along the unique path between vertices u and v in the tree (both inclusive). 
Input
First line of input contains an integer N denoting the size of the vertex set of the tree. Then follow N - 1 lines, ith of which contains two integers ai and bi denoting an edge between vertices ai and bi in the tree. After this follow N space separated integers in a single line denoting initial values vi at each of these nodes. Then follows a single integer Q on a line by itself, denoting the number of queries to follow. Then follow Q queries, each one on a line by itself. Each query is either a find query or a change query with format as given in problem statement. Note that all vertices are 0-based.
Output
For every find query, print the answer to that query in one line by itself.
Example

Input:
6
0 4
0 5
1 5
5 2
3 5
3 1 3 2 4 2
5
F 3 5
C 1 3 1
C 3 4 4
F 3 0
F 2 5

Output:
2
7
1

Example input:

Example output:


Solution:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=50015;
    int n,q,tot,val[maxn],now[maxn],pre[maxn<<1],son[maxn<<1];
    void connect(int u,int v){pre[++tot]=now[u];now[u]=tot;son[tot]=v;}
    void init(){
    	scanf("%d",&n);
    	for (int u,v,i=1;i<=n-1;++i){
    		scanf("%d%d",&u,&v);++u;++v;
    		connect(u,v);connect(v,u);
    	}
    	for (int i=1;i<=n;++i) scanf("%d",&val[i]);
    }
    struct Tbit{
    	int t[maxn];
    	int query(int x){
    		int res=0;
    		for (int p=x;p>=1;p-=p&-p) res+=t[p];
    		return res;
    	}
    	void modify(int l,int r,int v){
    		for (int p=l;p<=n;p+=p&-p) t[p]+=v;
    		for (int p=r+1;p<=n;p+=p&-p) t[p]-=v;
    	}
    }bit;
    int abs(int x){return x>0?x:-x;}
    int gcd(int a,int b){return !b?a:gcd(b,a%b);}
    struct Tsegment{
    	int t[maxn<<2];
    	void modify(int p,int l,int r,int x,int v){
    		if (l==r){t[p]+=v;return;}
    		int mid=(l+r)>>1;
    		if (x<=mid) modify(p<<1,l,mid,x,v);
    		else modify(p<<1|1,mid+1,r,x,v);
    		t[p]=gcd(t[p<<1],t[p<<1|1]);
    	}
    	int query(int p,int l,int r,int a,int b){
    		if (l==a&&r==b) return t[p];
    		int mid=(l+r)>>1;
    		if (b<=mid) return query(p<<1,l,mid,a,b);
    		else if (a>=mid+1) return query(p<<1|1,mid+1,r,a,b);
    		else return gcd(query(p<<1,l,mid,a,mid),query(p<<1|1,mid+1,r,mid+1,b));
    	}
    	void modify(int x,int v){modify(1,1,n,x,v);}
    	int query(int a,int b){return query(1,1,n,a,b);}
    }seg;
    int tim,seq[maxn],fa[maxn],dfn[maxn],top[maxn],dep[maxn],siz[maxn];
    int get_siz(int u,int f){
    	fa[u]=f;siz[u]=1;dep[u]=dep[f]+1;
    	for (int p=now[u];p;p=pre[p])
    		if (son[p]!=f) siz[u]+=get_siz(son[p],u);
    	return siz[u];
    }
    void get_top(int u,int t){
    	int idx=0;
    	dfn[u]=++tim;seq[tim]=u;top[u]=t;
    	for (int p=now[u];p;p=pre[p])
    		if (son[p]!=fa[u]&&siz[son[p]]>siz[idx]) idx=son[p];
    	if (idx) get_top(idx,t);
    	for (int p=now[u];p;p=pre[p])
    		if (son[p]!=fa[u]&&son[p]!=idx)
    			get_top(son[p],son[p]);
    }
    void query(int u,int v){
    	int res=0;
    	while (top[u]!=top[v]){
    		if (dep[top[u]]<dep[top[v]]) swap(u,v);
    		res=gcd(res,bit.query(dfn[top[u]]));
    		if (u!=top[u]) res=gcd(res,seg.query(dfn[top[u]]+1,dfn[u]));
    		u=fa[top[u]];
    	}
    	if (dep[u]<dep[v]) swap(u,v);
    	res=gcd(res,bit.query(dfn[v]));
    	if (u!=v) res=gcd(res,seg.query(dfn[v]+1,dfn[u]));
    	printf("%d\n",abs(res));
    }
    void modify(int u,int v,int w){
    	while (top[u]!=top[v]){
    		if (dep[top[u]]<dep[top[v]]) swap(u,v);
    		bit.modify(dfn[top[u]],dfn[u],w);
    		seg.modify(dfn[top[u]],w);
    		if (dfn[u]!=n) seg.modify(dfn[u]+1,-w);
    		u=fa[top[u]];
    	}
    	if (dep[u]<dep[v]) swap(u,v);
    	bit.modify(dfn[v],dfn[u],w);
    	seg.modify(dfn[v],w);
    	if (dfn[u]!=n) seg.modify(dfn[u]+1,-w);
    }
    void work(){
    	get_siz(1,0);get_top(1,1);
    	for (int i=1;i<=n;++i){
    		bit.modify(dfn[i],dfn[i],val[i]);
    		seg.modify(dfn[i],val[i]-val[seq[dfn[i]-1]]);
    	}
    	scanf("%d",&q);
    	for (int i=1;i<=q;++i){
    		char op[5];int u,v,w;
    		scanf("%s%d%d",op,&u,&v);++u;++v;
    		if (op[0]=='F') query(u,v);
    		else{scanf("%d",&w);modify(u,v,w);}
    	}
    }
    int main(){
    	init();
    	work();
    	return 0;
    }