#include using namespace std; #define ll long long #define rep(i, n) for (int i = 0; i < (int)(n); i++) template bool chmin(T& a, T b){if(a > b){a = b; return true;} return false;} template bool chmax(T& a, T b){if(a < b){a = b; return true;} return false;} const long long mod=998244353; const long long mod2=469762049; const long long mod100=1000000007; struct HLD{ //0-indexed //根が0の根付き木で実装 vectorV;//入りがけ順 vectorid;//頂点iがどこにあるか vectorhead;//頂点iが属するheavy pathの親 vectorchild;//頂点iが属するheavy pathの子 vector>G;//グラフ vectorsubtree;//部分木サイズ vectorparent;//自分の親 //初期化 HLD(int N){ id.assign(N,-1); head.assign(N,-1); child.assign(N,-1); subtree.assign(N,-1); parent.assign(N,-1); G.assign(N,{}); } //辺の追加 void add_edge(int u,int v){ G[u].push_back(v); G[v].push_back(u); } //テーブルの作成。辺を追加した後にやる void make_table(){ auto dfs1=[&](auto &dfs1,int pos,int last)->void { subtree[pos]=1; for(auto nex:G[pos]){ if(nex==last) continue; parent[nex]=pos; dfs1(dfs1,nex,pos); subtree[pos]+=subtree[nex]; } return; }; dfs1(dfs1,0,-1); auto dfs2=[&](auto &dfs2,int pos,int last,int h)->int { id[pos]=(int)V.size(); V.push_back(pos); head[pos]=h; pairpriority={-1,-1}; for(auto nex:G[pos]){ if(nex==last) continue; if(priorityid[v]) return v; else return u; } if(id[u]>id[v]){ u=parent[head[u]]; } else{ v=parent[head[v]]; } } } }; template struct lazysegtree{ using F1=function; using F2=function; using F3=function; vectornode; vectorlazy; int N;int log;F1 op;T e;F2 mapping;F3 composition;F id; lazysegtree(int n,F1 op,T e,F2 mapping,F3 composition,F id) :op(op),e(e),mapping(mapping),composition(composition),id(id){ N=1; log=1; while(N<=n){ N<<=1; log++; } node.assign(N*2,e); lazy.assign(N*2,id); } void set(int p,T x){ int pos=1; for(int i=log-2;i>=0;i--){ lazy[pos*2]=composition(lazy[pos*2],lazy[pos]); lazy[pos*2+1]=composition(lazy[pos*2+1],lazy[pos]); node[pos*2]=mapping(node[pos*2],lazy[pos]); node[pos*2+1]=mapping(node[pos*2+1],lazy[pos]); lazy[pos]=id; pos<<=1; if((p>>i)&1) pos++; } lazy[pos]=id; node[pos]=x; while(pos>=2){ pos/=2; node[pos]=op(node[pos*2],node[pos*2+1]); } return; } void apply(int l,int r,int a,int b,int u,F f){ if(b<=l || r<=a) return; if(l<=a && b<=r){ lazy[u]=composition(lazy[u],f); node[u]=mapping(node[u],f); return; } lazy[u*2]=composition(lazy[u*2],lazy[u]); lazy[u*2+1]=composition(lazy[u*2+1],lazy[u]); node[u*2]=mapping(node[u*2],lazy[u]); node[u*2+1]=mapping(node[u*2+1],lazy[u]); lazy[u]=id; int m=(a+b)/2; apply(l,r,a,m,u*2,f); apply(l,r,m,b,u*2+1,f); node[u]=op(node[u*2],node[u*2+1]); return; } void apply(int l,int r,F f){//[l,r)を変更 l++;r++; apply(l,r,1,N+1,1,f); } void apply(int p,F f){ p++; apply(p,p+1,1,N+1,1,f); } T fold(int l,int r,int a,int b,int u){ if(b<=l || r<=a)return e; if(l<=a && b<=r){ return node[u]; } int m=(a+b)/2; T L=mapping(fold(l,r,a,m,u*2),lazy[u]); T R=mapping(fold(l,r,m,b,u*2+1),lazy[u]); return op(L,R); } T fold(int l,int r){//[l,r)をを求める l++;r++; return fold(l,r,1,N+1,1); } T fold(int p){ p++; return fold(p,p+1,1,N+1,1); } }; struct D{ ll ans,infr; }; D e(){ D res; res.ans=0; res.infr=0; return res; } D op(D a,D b){ D res; res.ans=a.ans+b.ans; res.infr=a.infr+b.infr; res.ans%=mod100; res.infr%=mod100; return res; } D mapping(D x,ll f){ x.ans+=x.infr*f; x.ans%=mod100; return x; } ll composition(ll f,ll g){ return (f+g)%mod100; } int main(){ cout.tie()->sync_with_stdio(0); cin.tie(0); int N;cin>>N; HLD H(N); ll S[N],C[N]; for(int i=0;i>S[i]; for(int i=0;i>C[i]; int A[N-1],B[N-1]; for(int i=0;i>A[i]>>B[i]; A[i]--;B[i]--; H.add_edge(A[i],B[i]); } H.make_table(); int Q;cin>>Q; int query[Q],X[Q],Y[Q]; ll Z[Q]; for(int i=0;i>query[i]>>X[i]>>Y[i]; X[i]--;Y[i]--; if(query[i]==0) cin>>Z[i]; } lazysegtreeseg(N,op,e(),mapping,composition,0LL); for(int i=0;i