首页 > 其他分享 >Solution - Codeforces 622E Ants in Leaves

Solution - Codeforces 622E Ants in Leaves

时间:2024-10-11 21:10:40浏览次数:1  
标签:cnt 子树 622E int siz Leaves Solution dep operatorname

首先因为 \(1\) 点是可以一次性到多个点的,因此不需要考虑 \(1\) 点的情况,而是转而分析 \(1\) 的每个子树的情况,最后取 \(\max\)。

那么对于每个子树,就有每个节点每个时刻至多存在 \(1\) 个点的性质了。
考虑如何去求解。

首先一个贪心的想法是肯定是每个蚂蚁越早到一个点越好。
于是一个想法是考虑在 dfs 的时候合并。
即维护子树 \(u\) 内叶子到 \(u\) 的时间 \(S\),子树 \(v\) 内叶子到 \(v\) 的时间 \(T\)。
那么如果存在 \(x\in S\) 满足 \(x\in T\),那么就钦定这个蚂蚁先不往上爬,而是等到 \(x + 1\) 时刻继续爬,即 \(x\leftarrow x + 1\) 直到 \(x\not \in T\)。

但是问题在于合并的次数太多了,这个合并的方法也不太好用数据结构维护(其实可以启发式合并 + 线段树二分做到 \(\mathcal{O}(n\log^2 n)\))。

考虑到一个 \(x\in S\),这个 \(x\) 会和许多其他集合 \(T\) 合并,但是合并操作都是若 \(x\in T\),则 \(x\leftarrow x + 1\)。
那么这说明实际上各个集合是不区分的,那么就可以直接把所有的叶子放在根处合并。

即直接维护可重集合 \(S = \{\operatorname{dep}_u | u \operatorname{is\ leaf}\}\),那么若 \(S\) 中存在 \(c(c\ge 1)\) 个 \(x\),就直接钦定一个 \(x\) 到根,而剩下的 \(c - 1\) 个 \(x\) 就只能变为 \(x + 1\) 继续等待。
\(x\) 从小到大操作直到 \(S\) 为空,变为空的那个时刻就代表着最后一个叶子的蚂蚁跳到了根,这个时刻就是这个子树的答案。

容易发现这是与上述的递归合并过程等价的,因为这个让 \(c - 1\) 个 \(x\) 变为 \(x + 1\) 就代表着在合并过程中发现了其他的 \(x\) 选择了让步。

然后考虑优化 \(S\) 的变化的过程。
其实能够发现真正只关注每个 \(x\) 的个数 \(\operatorname{cnt}_x\)。
那么就可以直接递推,当 \(\operatorname{cnt}_x\ge 1\) 时有 \(\operatorname{cnt}_{x + 1}\leftarrow \operatorname{cnt}_{x + 1} + \operatorname{cnt}_x\)。

然后考虑一下这个过程中 \(x\) 最大会是多少。
一个很宽的上界是 \(\operatorname{size}(T) + \max \operatorname{dep}(T)\le 2\operatorname{size}(T)\)。
又因为 \(1\) 的所有子树 \(\operatorname{size}\) 之和 \(= n - 1\)。
所以可以知道实际上 \(\sum \max x\le 2n - 2\)。

于是时间复杂度就为 \(\mathcal{O}(n)\)。

#include<bits/stdc++.h>
const int maxn = 5e5 + 10;
std::vector<int> to[maxn];
int dep[maxn], cnt[maxn * 2], tot;
int dfs(int u, int fa) {
   dep[u] = dep[fa] + 1;
   if (to[u].size() == 1)
      cnt[dep[u]]++, tot++;
   int siz = 1;
   for (int v : to[u])
      if (v != fa)
         siz += dfs(v, u);
   return siz;
}
int main() {
   int n; scanf("%d", &n);
   for (int i = 1, x, y; i < n; i++)
      scanf("%d%d", &x, &y), to[x].push_back(y), to[y].push_back(x);
   int mx = 0;
   for (int u : to[1]) {
      int siz = dfs(u, 1);
      for (int i = 1; ; i++) {
         if (cnt[i])
            tot--, cnt[i + 1] += cnt[i] - 1;
         if (! tot) {
            mx = std::max(mx, i); break;
         }
      }
      memset(cnt + 1, 0, sizeof(int) * siz * 2);
   }
   return printf("%d\n", mx), 0;
}

标签:cnt,子树,622E,int,siz,Leaves,Solution,dep,operatorname
From: https://www.cnblogs.com/rizynvu/p/18459321

相关文章

  • PageRank parallel solutions
    Assignment4 DueFridayby11:59pmPoints70 SubmittingafileuploadAvailableOct4at12am-Dec24at11:59pmStartAssignment Assignment4(70Points) ueFridayOctober11@11:59PMInthisassignment,wewillimprovetheparallelsolutionsofPageRa......
  • Solution - Atcoder ARC116C Multiple Sequences
    一个\(\mathcal{O}(m^{\frac{3}{4}}\logm)\)做法。令\(a_0=1\)。对于倍数问题,考虑类似差分的思想,定义\(b_i=\frac{a_i}{a_{i-1}}(1\lei\len)\),那么合法的\(a\)和\(b\)是双射的,就只需要考虑对\(b\)计数了。考虑到因为有\(\prod\limits_{i=1}^nb_i\lem\)......
  • redis scalable solution -- twemproxy
    twemproxyhttps://github.com/twitter/twemproxyAfast,light-weightproxyformemcachedandredistwemproxy(nutcracker)twemproxy(pronounced"two-em-proxy"),akanutcrackerisafastandlightweightproxyformemcachedandredisprotocol.......
  • 【题解】Solution Set - NOIP2024集训Day42 博弈论
    【题解】SolutionSet-NOIP2024集训Day42博弈论https://www.becoder.com.cn/contest/5574https://www.cnblogs.com/CloudWings/p/17813917.html「中山市选2009」谁能赢呢?一道经典的「二分图博弈」在棋盘问题上的应用。https://www.luogu.com.cn/article/h8a79k3i......
  • CF2018E2 Solution
    CF2018E2Solution先考虑E1的做法。首先我们如果钦定一组\(k\)条线段的话,容易求出最大组数。简单来讲就是将所有端点按照右端点排序,这样只需要考虑一个偏序,然后扫描,将区间\([l_i,r_i]\)加一,当发现某个点的值为\(k\)时,就说明分成了一组方案。此时我们一定清空,然后记录当......
  • Solution - Atcoder ARC157E XXYX Binary Tree
    考虑这个不存在\(\texttt{YY}\)的限制,与\(\texttt{XX}\)个数为变量的限制相比较,看起来\(\texttt{Y}\)就更特殊,于是考虑从\(\texttt{Y}\)的视角来分析问题。同时考虑到因为有\(A+B+C=n-1\),所以\(\texttt{XX}\)其实也不是很重要,因为只需要让\(\texttt{XY}\)和......
  • Solution - Atcoder ARC157D YY Garden
    考虑到因为有横轴数轴两部分的限制,不妨先固定下来一部分的限制再处理另一部分。对于这题来说横轴竖轴本质是相同的,于是不妨考虑固定横轴。如果知道了横轴的分割,那么对于竖轴上就可以根据分割情况知道合法的分割了。即考虑记\(f_i\)为考虑了竖轴的前\(i\)列,第\(i\)列为最......
  • AT_abc_373F Solution
    AT_abc_373FSolution\(O(n^3)\)的dp很容易想到,枚举重量,枚举物品,枚举物品选择数量,我们考虑把它优化到\(O(n^2)\),显然重量与物品的枚举不能避免,所以我们考虑省去数量的枚举。记\(num_{i,j}\)表示总质量为i价值达到最大时,j选择了多少个,对于当前枚举的重量i,我们枚举......
  • Solution - Kilonova 2837 P2
    先考虑q2。考虑到如果是以\(2^N\)为入手点因为进位的原因看起来就做不了。于是考虑以\(M\)为前缀入手。考虑刻画出\(M\)为前缀的数\(x\)的形式。可以考虑根据\(M\)后面的位数\(k\)来刻画,有\(x\in\bigcup_{k=0}^{\lfloor{\frac{L}{\log_210}}\rfloor}[M\tim......
  • P9676 [ICPC2022 Jinan R] Skills Solution
    P9676[ICPC2022JinanR]SkillsSolution拿到题目之后我们先考虑一个朴素dp:记\(f_{i,0/1/2,x,y}\)表示第\(i\)天,我们学习第1/2/3个技能,同时按照序号顺延下去的另两个技能分别有\(x,y\)天未学习的最大经验总和。这很明显是一个\(O(n^3)\)的dp,转移方程比较简单。我们......