zoukankan      html  css  js  c++  java
  • Solution -「ARC 125F」Tree Degree Subset Sum

    (mathcal{Description})

      Link.

      给定含有 (n) 个结点的树,求非负整数对 ((x,y)) 的数量,满足存在 (exist Ssubseteq V,~|S|=xlandsum_{uin S}d_u=y),其中 (d_u) 表示点 (u) 的度数。

      (nle2 imes10^5)

    (mathcal{Solution})

      方便期间,以下所有 (d_u) 表示 (u) 的度数 (-1)

      出题人莫名其妙告诉你一棵树,无非是强调 (sum d=n-2),自然想到根号分治。不过朴素 DP 的状态数量就已经难以接受,我们需要更多的结论。

      比如这个结论:

    结论:若 (x_1le x_2)((x_1,y),(x_2,y)) 均合法,那么 (forall x_3in[x_1,x_2],~(x_3,y)) 也合法。

    证明   对于某个 $y$,取出最小 $x_l$ 和最大的 $x_r$,使得 $(x_l,y),(x_r,y)$ 合法。设 ${d_n}$ 中有 $z$ 个值为 $0$,则我们只需证明 $x_r-x_lle 2z$,这是由于 $(x_l,y)$ 的选取中必然不含 $0$,那么 $(x_l+1,y),(x_l+2,y),cdots,(x_l+z,y)$ 都合法,$(x_r-k,y)$ 同理。

      考虑任意一个 (Ssubseteq V),令 (d_S=sum_{uin S}d_u),那么

    • (d_S-|S|ge -z),显然;
    • (d_S-|S|le z-2)(d_Sle sum d=n-2),取等时 (|S|ge n-z),得证。

      即 (-zle d_S-|S|le z-2),考虑将 ((x_l,y))((x_r,y)) 代入,有 (-zle y-x_rle y-x_lle z-2),可以推出 (x_r-x_lle 2z-2),故已有原命题成立。 (square)

      所以,我们只需要对于每个 (y),DP 求出 (x_l)(x_r) 就能得到答案。DP 时根号分治,内部用单调队列优化即可。复杂度 (mathcal O(nsqrt n))

    (mathcal{Code})

    /*~Rainybunny~*/
    
    #include <bits/stdc++.h>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    typedef long long LL;
    
    const int MAXN = 2e5;
    int n, d[MAXN + 5], f[MAXN + 5], g[MAXN + 5];
    
    inline void trans( const int v, const int c, const int r,
      int* h, const auto& cmp ) { // cmp(a,b) is true <=> a is the better value.
        static int que[MAXN + 5], th[MAXN + 5];
        int hd = 1, tl = 0;
        for ( int i = r; i <= n - 2; i += v ) {
            th[i] = h[i];
            while ( hd <= tl && que[hd] + c * v < i ) ++hd;
            while ( hd <= tl
              && cmp( th[i] - i / v, th[que[tl]] - que[tl] / v ) ) --tl;
            que[++tl] = i;
            h[i] = th[que[hd]] + ( i - que[hd] ) / v;
        }
    }
    
    int main() {
        scanf( "%d", &n );
        rep ( i, 1, n ) d[i] = -1;
        rep ( i, 2, n ) {
            int u, v; scanf( "%d %d", &u, &v );
            ++d[u], ++d[v];
        }
    
        std::sort( d + 1, d + n + 1 );
        memset( f, 0x3f, sizeof f ), memset( g, 0xc0, sizeof g );
        f[0] = g[0] = 0;
        for ( int l = 1, r; l <= n; l = r + 1 ) {
            for ( r = l; r < n && d[r + 1] == d[l]; ++r );
            int v = d[l], c = r - l + 1;
            if ( !v ) { g[0] = c; continue; }
            rep ( r, 0, v - 1 ) {
                trans( v, c, r, f,
                  []( const int u, const int v ) { return u < v; } );
                trans( v, c, r, g,
                  []( const int u, const int v ) { return u > v; } );
            }
        }
    
        LL ans = 0;
        rep ( i, 0, n - 2 ) {
            // printf( "%d: [%d,%d]
    ", i, f[i], g[i] );
            if ( f[i] <= g[i] ) ans += g[i] - f[i] + 1;
        }
        printf( "%lld
    ", ans );
        return 0;
    }
    
    
  • 相关阅读:
    Ubuntu 开发环境
    机器学习笔记-相似度
    ElasticSearch 笔记-分布式工作原理
    ElasticSearch 笔记-别名
    ElasticSearch 笔记-映射
    ElasticSearch 笔记-基本概念
    Linux 二 常用命令
    经典中的经典算法:动态规划(详细解释,从入门到实践,逐步讲解)
    图解Transformer
    CUDA9.0+tensorflow-gpu1.8.0+Python2.7服务器环境搭建经验
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15177264.html
Copyright © 2011-2022 走看看