Solution 线段树好题. 我们考虑用last[i]表示\(i\)这个位置的颜色的上一个出现位置. 考虑以一个位置\(R\)为右端点的区间最远能向左延伸到什么位置: \(L = \max_{i \le j} last[j]\). 而我们的答案就等于 \[ sum_{i = 1}^n (i - (max_{1 \le j \le i} last[j])) = \sum_{i = 1}^n i - \sum_{i = 1}^n max_{1 \le j \le i} last[j] \] 第一项…
Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内容题解已经写得很详细了, 直接看题解吧: 线性的LIS的经典做法:从左往右扫并维护f[x]表示当前长为x的LIS的最后一个数最小是多少,易证f[x]必定递增,每次新加一个数y,则在f中二分查找最小的x使得f[x]>=y,若找到则将f[x]设为y,否则在f末尾加上y.最后f的长度即为答案. 答案一定是…
Solution 相当于要你计算这样一个式子: \[ \sum_{x = 0}^m \left( \begin{array}{} m \\ x \end{array} \right) \left( \begin{array}{} k \\ n - m + 2x \end{array}{} \right) \] 考虑到\(m\)非常大, 而\(k\)却比较小, 我们尝试将\(x\)的\(m\)相关转化为\(k\)相关. 我们用如下现实意义来考虑: 令\(N = n - m\), 则我们相当于有两堆…
Solution 这是一道好题. 考虑球体的体积是怎么计算的: 我们令\(f_k(r)\)表示\(x\)维单位球的体积, 则 \[ f_k(1) = \int_{-1}^1 f_{k - 1}(\sqrt{1 - r^2}) dr \] 然而\(f_{k - 1}(\sqrt{1 - x^2})\)并不容易处理, 我们又注意到\(k\)维球体的体积可以表示为\(a \pi r^k\), 因此\(f_k(\sqrt{1 - r^2}) = f_k(1) \times (1 - r)^{\frac…
Solution 这题实际上并不是构造题, 而是一道网络流. 我们考虑题目要求的一条路径应该是什么样子的: 它是一个环, 并且满足每个点有且仅有一条出边, 一条入边, 同时这两条边的权值还必须不一样. 考虑如何建图: 我们对每个景点分别建一个点, 源点连向左岸的景点, 右岸的景点连向汇点, 边的容量都是2, 这限制了一个点最多只能连两条边; 我们再将一个点拆成\(k\)个, 每个代表一个连入的边的权值, 也就是说对于连入一个点的所有边, 都连在代表该边的权值的点上; 一个景点与其拆成的\(k\)…
Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道题有两种思路. 比较容易想到的(也是我考场上想的)一种是: 把所有任务按照权值从大到小排序, 从权值大的开始安排, 将其安排在尽可能靠后的位置; 假如位置不够, 安排不下, 则可停止. 但这样非常难统计答案, 我想到的做法是用线段树的分裂与合并来维护整个区间. 但考虑到时间复杂度以及常数大小, 还是…
Solution 这题的解法很妙啊... 考虑这三个点可能的形态: 令它们的重心为距离到这三个点都相同的节点, 则其中两个点分别在重心的两棵子树中, 且到重心的距离相等; 第三个点可能在重心的一棵不同于前两个点子树上, 也有可能在重心往上走可以到达的位置上. 定义数组\(f[i][j]\)表示在以\(i\)为根的子树下与\(i\)的距离为\(j\)的节点个数; \(g[i][j]\)表示在以\(i\)为根的子树下, 有多少个点对满足如下条件: 这个点对到它们LCA的距离相同, 我们假设其为\(d…
Solution 正解是一个\(\log\)的link-cut tree. 将一条边拆成两个事件, 按照事件排序, link-cut tree维护联通块大小即可. link-cut tree维护子树大小非常不熟练. 正确的做法是每个点开两个变量size和add, 分别表示在splay中以这个点为根的所有点所在的子树的点的数量, 以及以当前点为根的子树由虚边贡献的点的数量. #include <cstdio> #include <cctype> #include <algori…
Solution 考虑怎么卖最赚钱: 肯定是只卖不买啊(笑) 虽然说上面的想法很扯淡, 但它确实能给我们提供一种思路, 我们能不买就不买; 要买的时候就买最便宜的. 我们用一个优先队列来维护股票的价格, 从前往后扫描. 假设我们已经知道了到前一天的最优策略, 考虑到当前这一天的最优策略: 假如手上还有股票, 那么一定是要把它卖掉的; 假如已经没有股票了, 那么我们就在原本打算卖出的股票以及这一天的股票中选出股价最低的买入. 用优先队列维护股价, 从第一天往后扫描即可. #include <cst…