AtCoder Beginner Contest 173 F - Intervals on Tree
给出一棵 N ( 1 ≤ N ≤ 2 × 1 0 5 ) N(1 \le N \le 2\times10^5) N(1≤N≤2×105)个顶点(编号从 1 1 1开始)的树,定义
f ( L , R ) f(L,R) f(L,R):顶点集 V ′ = { L , L + 1 , L + 2 , ⋯ , R } V'=\{L, L+1, L+2,\cdots,R\} V′={L,L+1,L+2,⋯,R}的导出子图(由 顶点集 V ′ V' V′ 和 两端点都在顶点集 V ′ V' V′中的边 构成的子图)的连通块数量。
求: ∑ L = 1 N ∑ R = L N f ( L , R ) \displaystyle\sum_{L=1}^N\sum_{R=L}^Nf(L,R) L=1∑NR=L∑Nf(L,R)。
对于一棵树的点导出子图,可以发现每一个连通块一定是一棵树,即树的点导出子图是森林,则有:
设 g ( L , R ) g(L,R) g(L,R)为对应导出子图中的总顶点数, h ( L , R ) h(L,R) h(L,R)为对应导出子图中的总边数,则有:
a n s = ∑ L = 1 N ∑ R = L N [ g ( L , R ) − h ( L , R ) ] = ∑ L = 1 N ∑ R = L N g ( L , R ) − ∑ L = 1 N ∑ R = L N h ( L , R ) ans = \sum_{L=1}^N\sum_{R=L}^N[g(L,R)-h(L,R)] = \sum_{L=1}^N\sum_{R=L}^Ng(L,R)-\sum_{L=1}^N\sum_{R=L}^Nh(L,R) ans=L=1∑NR=L∑N[g(L,R)−h(L,R)]=L=1∑NR=L∑Ng(L,R)−L=1∑NR=L∑Nh(L,R)
前者即为所有区间 [ L , R ] [L,R] [L,R] 的长度和;后者可计算每条边的贡献(即有多少个区间 [ L , R ] [L,R] [L,R] 的导出子图包含该边)相加;
#include
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const LL LINF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 2e5 + 10;
int N, u[maxn], v[maxn];
int main()
{
scanf("%d", &N);
for(int i = 1; i <= N - 1; i++)
scanf("%d %d", &u[i], &v[i]);
LL ans = 0;
for(int i = 1; i <= N; i++)
ans += (LL) i * (N - i + 1);
for(int i = 1; i <= N - 1; i++)
{
if(u[i] > v[i])
swap(u[i], v[i]);
ans -= (LL) u[i] * (N - v[i] + 1);
}
printf("%lld\n", ans);
return 0;
}