AtCoder Beginner Contest 173 F - Intervals on Tree(树的点导出子图连通块数量)

AtCoder Beginner Contest 173 F - Intervals on Tree

题意:

给出一棵 N ( 1 ≤ N ≤ 2 × 1 0 5 ) N(1 \le N \le 2\times10^5) N(1N2×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=1NR=LNf(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=1NR=LN[g(L,R)h(L,R)]=L=1NR=LNg(L,R)L=1NR=LNh(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;
}

你可能感兴趣的:(★水题之路)