树链剖分。。
沃日打错树剖+路径并
感觉要滚粗啊
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
#define ll long long
const
ll Mod=1ll<<31;
char c;
inline void read(ll &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
struct Chain
{
Chain *next;
ll u;
}*Head[300001];
#define ll long long
ll Dep[300001];
namespace LC
{
ll Len[600001];
ll ST[1000001][20];
ll In[600001];
ll Block[600001];
ll tot;
inline ll L(ll x,ll y){return Dep[x]<Dep[y]?x:y;}
inline ll LCA(ll a,ll b)
{
if(!(a^b))return a;
ll x=In[a],y=In[b];
if(x>y)swap(x,y);
ll Len=y-x+1,Bl=Block[Len];
return L(ST[x][Bl],ST[y-(1<<Bl)+1][Bl]);
}
ll Dis(ll u,ll v){return Len[u]+Len[v]-2*Len[LCA(u,v)];}
inline void Bg()
{
Len[0]=1ll<<29;
Dep[0]=1ll<<29;
ll base;
for(ll i=1,base=1;i<=19;i++,base<<=1)
for(ll j=1;j<=tot;j++)
ST[j][i]=L(ST[j][i-1],ST[j+base][i-1]);
ll con=0;
for(ll i=1;i<=tot;i++)
if(i^(i&-i))Block[i]=con-1;
else Block[i]=con++;
}
void DFS(ll u,ll fa,ll dep)
{
Dep[u]=dep;
ST[In[u]=++tot][0]=u;
for(Chain*tp=Head[u];tp;tp=tp->next)
if(tp->u^fa)
{
DFS(tp->u,u,dep+1);
ST[++tot][0]=u;
}
if(u^fa)return ;
Bg();
}
}
ll t;
namespace Seg
{
struct N
{
ll l,r;
ll sum,flag;
}T[600001];
inline void Build(ll place,ll l,ll r)
{
ll Mid=l+r>>1,lc=place<<1,rc=lc|1;
T[place].l=l,T[place].r=r;
if(l^r)
Build(lc,l,Mid),Build(rc,Mid+1,r);
}
inline void AddFlag(ll place,ll Delta)
{
T[place].flag+=Delta,T[place].sum+=Delta*(T[place].r-T[place].l+1);
T[place].flag%=Mod,T[place].sum%=Mod;
}
inline void pushdown(ll place)
{
ll lc=place<<1,rc=lc|1;
T[lc].flag+=T[place].flag,T[rc].flag+=T[place].flag;
T[lc].sum+=T[place].flag*(T[lc].r-T[lc].l+1),
T[rc].sum+=T[place].flag*(T[rc].r-T[rc].l+1);
T[lc].flag%=Mod;T[rc].flag%=Mod;
T[lc].sum%=Mod;T[rc].sum%=Mod;
T[place].flag=0;
}
void Add(ll place,ll l,ll r,ll Delta)
{
if(T[place].l>=l&&T[place].r<=r)
{ AddFlag(place,Delta);return;}
// if(T[place].flag)pushdown(place);
ll lc=place<<1,rc=lc|1,Mid=T[lc].r;
if(Mid<r)Add(rc,l,r,Delta);
if(Mid>=l)Add(lc,l,r,Delta);
T[place].sum=(T[lc].sum+T[rc].sum+T[place].flag*(T[place].r-T[place].l+1))%Mod;
}
ll Query(ll place,ll l,ll r)
{
if(T[place].l>=l&&T[place].r<=r)return T[place].sum;
// if(T[place].flag)pushdown(place);
ll res=T[place].flag*(min(r,T[place].r)-max(l,T[place].l)+1),lc=place<<1,rc=lc|1,Mid=T[lc].r;
if(l<=Mid)res+=Query(lc,l,r);
if(r>Mid)res+=Query(rc,l,r);
res%=Mod;
return res;
}
}
struct Path{ll f,s;};
Path operator &(Path a,Path b)
{
Path res;
res.f=LC::LCA(a.f,b.f);
if(res.f==b.f)res.f=a.f;
else if(res.f==a.f)res.f=b.f;
else return (Path){-1,-1};
res.s=LC::LCA(a.s,b.s);
if(Dep[res.f]>Dep[res.s])return (Path){-1,-1};
return res;
}
ll K;
Path X[30001];
ll HeavySon[300001],Size[300001],F[300001];
void DFS(ll u,ll f)
{
Size[u]++;
F[u]=f;
for(Chain *tp=Head[u];tp;tp=tp->next)
if(tp->u!=f)
{
DFS(tp->u,u);
Size[u]+=Size[tp->u];
if(Size[tp->u]>Size[HeavySon[u]])HeavySon[u]=tp->u;
}
}
ll tot,CBG[300001],CED[300001],CPL[300001],CND[300001];
void DFS2(ll u,ll f,ll BG)
{
CBG[u]=BG;
CND[CPL[u]=++tot]=u;
if(HeavySon[u])
DFS2(HeavySon[u],u,BG);
for(Chain *tp=Head[u];tp;tp=tp->next)
if(tp->u!=HeavySon[u]&&tp->u!=f)
DFS2(tp->u,u,tot+1);
CED[u]=tot;
}
ll Query(Path X)
{
ll res=0,u=X.f,v=X.s;
while(CBG[v]!=CBG[u])
{
res+=Seg::Query(1,CBG[v],CPL[v]);
v=F[CND[CBG[v]]];
}
res+=Seg::Query(1,CPL[u],CPL[v]);
return res;
}
ll Add(ll u,ll Delta)
{
Seg::Add(1,CPL[u],CED[u],Delta);
}
ll Div(ll x,Path Tp)
{
if(x==K+1)return 0;
if(Tp.f==4&&Tp.s==4)
x++,x--;
if(Tp.f==-1)return 0;
ll res=Query(Tp);
for(ll i=x+1;i<=K;i++)
res-=Div(i,Tp&X[i]),res%=Mod;
return res%Mod;
}
inline void ADD(ll a,ll b)
{
Chain *tp=new Chain;
tp->u=b,tp->next=Head[a],Head[a]=tp;
}
ll n,Q ;
int main()
{
read(n);
ll i,j,k,l;
for(i=1;i<n;i++)
{
read(j),read(k),ADD(j,k),ADD(k,j);
}
LC::DFS(1,1,1);
DFS(1,1);
DFS2(1,1,1);
Seg::Build(1,1,tot);
read(Q);
while(Q--)
{
ll op;
read(op);
if(op)
{
read(K);
ll ans=0,j,k;
for(i=1;i<=K;i++)
{
read(j),read(k);
X[i].f=Dep[j]<Dep[k]?j:k;
X[i].s=j+k-X[i].f;
}
for(i=1;i<=K;i++)
ans+=Div(i,X[i]);
printf("%lld\n",(ans%Mod+Mod)%Mod);
}
else read(j),read(k),Add(j,k);
}
// printf("%d\n",t);
return 0;
}