还是来致敬一下那过往吧
题目分析
先丢代码
#include<bits/stdc++.h>
const int maxn = ;
const int maxm = ;
const int maxNode = ; struct node
{
int top,son,fa,tot;
}a[maxn];
struct point
{
int u,v;
point(int a=, int b=):u(a),v(b) {}
};
struct tree
{
int ls,rs,cov,val;
}f[maxNode];
int n,m,tot;
long long ans,det;
int chain[maxn],chTot,rt[maxn];
int edgeTot,head[maxn],edges[maxm],nxt[maxm],dep[maxn];
std::vector<point> opt[maxn];
std::vector<int> inc[maxn],dec[maxn]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void addedge(int u, int v)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
}
void dfs1(int x, int fa)
{
dep[x] = dep[fa]+, a[x].tot = ;
a[x].top = a[x].son = -, a[x].fa = fa;
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (v==fa) continue;
dfs1(v, x), a[x].tot += a[v].tot;
if (a[x].son==-||a[a[x].son].tot < a[v].tot)
a[x].son = v;
}
}
void dfs2(int x, int top)
{
a[x].top = top, chain[x] = ++chTot;
if (a[x].son==-) return;
dfs2(a[x].son, top);
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=a[x].fa&&edges[i]!=a[x].son)
dfs2(edges[i], edges[i]);
}
void splitChain(int id, int u, int v)
{
inc[u].push_back(id), inc[v].push_back(id);
while (a[u].top!=a[v].top)
{
if (dep[a[u].top] > dep[a[v].top]) std::swap(u, v);
opt[id].push_back(point(chain[a[v].top], chain[v]));
v = a[a[v].top].fa;
}
if (dep[u] > dep[v]) std::swap(u, v);
opt[id].push_back(point(chain[u], chain[v]));
dec[u].push_back(id), dec[a[u].fa].push_back(id);
}
void pushup(int rt, int len)
{
if (f[rt].cov) f[rt].val = len;
else f[rt].val = f[f[rt].ls].val+f[f[rt].rs].val;
}
void mergeSeg(int &u, int v, int l, int r)
{
if (!u||!v) u += v;
else{
int mid = (l+r)>>;
f[u].cov += f[v].cov;
mergeSeg(f[u].ls, f[v].ls, l, mid);
mergeSeg(f[u].rs, f[v].rs, mid+, r);
}
pushup(u, r-l+);
}
void update(int &rt, int L, int R, int l, int r, int c)
{
if (!rt) rt = ++tot;
if (L <= l&&r <= R) f[rt].cov += c, pushup(rt, r-l+);
else{
int mid = (l+r)>>;
if (L <= mid) update(f[rt].ls, L, R, l, mid, c);
if (R > mid) update(f[rt].rs, L, R, mid+, r, c);
}
pushup(rt, r-l+);
}
void delta(int x, int fa)
{
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=fa) delta(edges[i], x);
for (int l=; l<inc[x].size(); l++)
for (int i=,mx=opt[inc[x][l]].size(); i<mx; i++)
update(rt[x], opt[inc[x][l]][i].u, opt[inc[x][l]][i].v, , n, );
for (int l=; l<dec[x].size(); l++)
for (int i=,mx=opt[dec[x][l]].size(); i<mx; i++)
update(rt[x], opt[dec[x][l]][i].u, opt[dec[x][l]][i].v, , n, -);
int val = f[rt[x]].val;
if (val) ans += val, ++det;
mergeSeg(rt[fa], rt[x], , n);
}
int main()
{
memset(head, -, sizeof head);
n = read(), m = read();
for (int i=; i<n; i++)
addedge(read(), read());
dfs1(, ), dfs2(, );
for (int i=; i<=m; i++)
splitChain(i, read(), read());
delta(, );
printf("%lld\n",(ans-det)/);
return ;
}