題目大意

n<=300000，q<=300000，∑m<=300000。

什么是虛樹呢？

（這里引用了別人的一些資料與圖，供大家學習。）

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fd(i,a,b) for (int i=a;i>=b;i--)
#define INF 1 << 30
#define N 600005

using namespace std;

{
char ch = ' ';
int q = 0, w = 1;
for (;(ch != '-') && ((ch < '0') || (ch> '9'));ch = getchar());
if (ch == '-') w = -1,ch = getchar();
for (; ch >= '0' && ch <= '9';ch = getchar()) q = q * 10 + ch - 48;
n = q * w;
return n;
}

namespace ib {char b[100];}

inline void pint(int x)
{
if (x == 0)
{
putchar(48);
return;
}
if (x < 0)
{
putchar('-');
x = -x;
}
char *s = ib :: b;
while (x) *(++ s) = x % 10,x /= 10;
while (s != ib :: b) putchar((* (s --)) + 48);
}

typedef long long ll;

struct Edge
{
int to,next;
Edge(void){}
Edge(int a,int b) : to(a),next(b){}
}E[N];

int tot = 0,n,Q;
int Final[N];

{
E[++ tot] = Edge(y,Final[x]),Final[x] = tot;
E[++ tot] = Edge(x,Final[y]),Final[y] = tot;
}

void Dfs_rt(int x)
{
Dfsn[x] = ++ C;
Son[x] = 1;
for (int k = Final[x];k;k = E[k].next)
{
Dep[E[k].to] = Dep[x] + 1;
Dfs_rt(E[k].to);
Son[x] += Son[E[k].to];
}
}

void Build_rt()
{
Dfs_rt(1);
fo(g,1,19)
fo(i,1,n)
if (Up[i][g - 1]) Up[i][g] = Up[Up[i][g - 1]][g - 1];
}
////jump up (x=fa[x]) until dep[x]=d
int Jump(int x,int d)
{
fd(i,19,0)
if (!Up[x][i] || Dep[Up[x][i]] < d);else x = Up[x][i];
return x;
}

int Lca(int x,int y)
{
if (Dep[x] > Dep[y]) swap(x,y);
y = Jump(y,Dep[x]);
if (x == y) return x;
fd(i,19,0)
if (Up[x][i] != Up[y][i]) x = Up[x][i],y = Up[y][i];
}

typedef pair<int,int> P;
bool cmp_Dfsn(int a,int b) { return Dfsn[a] < Dfsn[b];}
int ss[N],vs[N],st[N],vfa[N],emp[N],vfe[N],ans[N],ss_[N],vn,stn = 0,sn;
P Dot[N]; //(dis,controller)
//vs: points in vtree
void Build_vt()
{
vn = stn = 0;
fo(i,1,sn) ss_[i] = ss[i];
sort(ss + 1,ss + 1 + sn,cmp_Dfsn);
fo(i,1,sn)
{
vs[++ vn] = ss[i];
Dot[ss[i]] = P(0,ss[i]);
ans[ss[i]] = 0;
}
fo(i,1,sn)
{
int x = ss[i];
if (! stn)
{
st[++ stn] = x;
vfa[x] = 0;
continue;
}
int lca = Lca(x,st[stn]);
for (;Dep[st[stn]] > Dep[lca];stn --)
if (Dep[st[stn - 1]] <= Dep[lca]) vfa[st[stn]] = lca;
if (st[stn] != lca)
{
vs[++ vn] = lca;
Dot[lca] = P(INF,0);
vfa[lca] = st[stn];
st[++ stn] = lca;
}
vfa[x] = lca;
st[++ stn] = x;
}
sort(vs + 1,vs + 1 + vn,cmp_Dfsn);//注意到按dfs序排序是滿足兒子一定在父親的后面的
fo(i,1,vn)
{
int x = vs[i];
emp[x] = Son[x];
if (i > 1) vfe[x] = Dep[x] - Dep[vfa[x]];
}
fd(i,vn,2)
{
int x = vs[i],
f = vfa[x];
Dot[f] = min(P(Dot[x].first + vfe[x],Dot[x].second),Dot[f]);
}
fo(i,2,vn)
{
int x = vs[i],
f = vfa[x];
Dot[x] = min(P(Dot[f].first + vfe[x],Dot[f].second),Dot[x]);
}
fo(i,1,vn)
{
int x = vs[i],
f = vfa[x];
//樹根往上的點
if (i == 1)
{
ans[Dot[x].second] += n - Son[x];
continue;
}
int fp = Jump(x,Dep[f] + 1),
cnt = Son[fp] - Son[x];
emp[f] -= Son[fp]; //這一棵子樹已經處理過了
if (Dot[f].second == Dot[x].second)
{
ans[Dot[x].second] += cnt;
continue;
}
int mid = Dep[x] - (Dot[f].first + Dot[x].first + vfe[x]) / 2 + Dot[x].first;
if ((Dot[f].first + Dot[x].first + vfe[x]) % 2 == 0 && Dot[f].second < Dot[x].second) mid ++;
int tmp = Son[Jump(x,mid)] - Son[x];
ans[Dot[x].second] += tmp;
ans[Dot[f].second] += cnt - tmp;
}
fo(i,1,vn) ans[Dot[vs[i]].second] += emp[vs[i]];
fo(i,1,sn)
{
pint(ans[ss_[i]]);
putchar(' ');
}
putchar(10);
}
int main()
{
freopen("worldtree.in","r",stdin);
freopen("worldtree.out","w",stdout);
fo(i,1,n - 1)
{
int x,y;
}
Build_rt();
while (Q --)
{