训练记录PART7 2018.11.30~2019.1.29

友情提醒:大部分题选自opentrains,以后有训练需要的同学慎重查看。

T111-XIX Open Cup - Grand Prix of SPb I

  题意:judge程序有一个奇数 \(X(1 \leq X < 2^{31})\)。你必须给它 \(N(\leq 10^5)\)个互不相同的数),它会随机选择 \(\frac{N}{2}\)\(N\) 是偶数),计算 \(a_i \times X \mod 2^{31}\) 并打乱输出。要求对于不同的 \(N\),构造 \(a_i\) 以还原 \(X\)
  题解:看起来很神奇,其实是一个暴力。注意到 \(X\) 是奇数,模数是 \(2\) 的幂次,有逆元。
  不妨设返回的是 \(b_i\)。假设我们关注 \(b_1\)。我们只需只要它对应哪个 \(a_i\),我们就能求出 \(X\)。于是这里就有一个 \(N^2\) 的做法了。枚举每一个 \(a_i\),得到一个可能的 \(X\) 的值。再把 \(X\) 和每个 \(a_i\) 去计算,如果得到的 \(N\) 个数里包含 \(b_i\)\(\frac{N}{2}\) 个数,\(X\) 可以认为是合法的。
  其实如果我们反过来check,就可以大大的剪枝。枚举了 \(X\) 后,每次用 \(b_i\) 去除,必须保证得到的 \(a_i\) 在你的列表里。如果不在即可 \(break\)。你还会发现,如果所有东西都是随机的话,如果 \(X\) 不是解,期望 \(O(1)\) 步就会被 \(break\),所以复杂度是 \(N \log N\) 的。\(log\) 是扩欧求逆元。

T112-2018 Bytedance-MW Wintercamp Selection Contest C

  题意:给出一棵 \(N(\leq 10^6)\) 个点的带边权的树。甲乙两人轮流博弈,每次可以选择将一条边 \(e\) 的边权 \(w_e\) 减一。若减完后变成 \(0\),则割掉不包含根的那个连通块。双方执最优策略,问先手是否必胜。如果必胜的话,还要输出所有可行的第一步删边方案。
  题解:如果边权 \(w_e=1\),有一个很简单的结论:子树 $sg_x=(sg_{y_1}+1) \oplus (sg_{y_2}+1) \dots $。这个可以用归纳法来证明。
  此题中边权可以大于 \(1\)。事实上,还有一个一般性的基于图的做法。
  链接可参考这里:([https://blog.csdn.net/acm_cxlove/article/details/7854532)。
  主要思想是基于对原图进行等价变换。
    等价变换①:偶环可以“缩成”一个点(偶环里的边将变成这个点的子环)。
    等价变换②:自环可以拆成一个新的儿子。
  直接将此题的树看成图,可以发现子树 \(sg_y\)\(sg_x\) 的贡献是 \(sg_y \oplus [w_{x,y} \nmid 2]\) 。特殊情况是 \(sg_y+1[w_{x,y}=1]\)
  第二问要求我们将某一条边减少一,使根的 \(sg\) 变为 \(0\)。直接 \(DFS\) 下去,每次维护需要将当前的 \(sg\) 变成多少才能合法。

T112-2018 Bytedance-MW Wintercamp Selection Contest D

  题意:定义 \(f(x,y)(x \geq y)\)\(x\) 变为 \(y\) 的最小步数。变化可以有两种:
    ①:\(x=x-1\)
    ②:\(x=x-2^i\)(如果 \(x\) 里含 \(2^i\)
  求 \(\sum \limits_{x=0}^n \sum \limits_{y=0}^x f(x,y)\)。答案对大质数取模。 \(n\) 的二进制表示不超过 \(500\) 位。
  题解:如果 \(x\) 某一位是 \(0\)\(y\)\(1\),只能通过操作 ① 来得到。我们只需将右侧尽快变成全 \(0\),然后执行 ① 操作。
  那么是找到最靠左的那个 \((0,1)\) 的 pair 吗?并不是。如 \(110001\)\(010010\),第五位不够退位的时候,会把第二位的 \(1\) 变成 \(0\),导致第二位变成新的 \((0,1)\) pair了。那还不如操作第二位呢!
  总结一下,我们要找一个最靠左的分界线,满足分界线右侧 \(x' < y'\)。一个推论是,分界线左侧第一位一定是 \((1,0)\) 的形式。然后我们知道这个 \(1\) 必然会被退位,所以最小步数为:分界线左侧 \((1,0)\) 的个数 + \(x'\)\(1\) 的个数+ \(y'\)\(0\) 的个数。
  考虑数位dp,\(f_{i,j}\) 表示到 \(x\)\(y\) 填到第 \(i\) 位,且目前 \((1,0)\) 的对数为 \(j\) 的方案数(当然还要加一些必要的 \(0/1\) 维来维护大小关系)。转移时候强制不出现 \((0,1)\)
  然后我们枚举分解线 \(i\)。我们要调用的右侧信息是 \(G_{i+1,j}\),表示“填 \(i+1\)~\(n\)\(x'\)\(y'\)\(x'<y'\)),\(x'\)\(1\) 的个数 + \(y'\)\(0\) 的个数为 \(j\) ”的方案数。这也可以通过一个 \(dp\) 预处理出。统计答案前对 \(G\) 做一个前缀和,总复杂度可以做到 \(O(L^2)\)
  还存在直接 \(O(L)\) 的优秀做法。\(F\) 里不仅要记方案数,也要记总的值。

T114-Petrozavodsk Winter 2009 - Andrew Stankevich Contest 37 E

  题意\(S,T\) 是字符串。我们在 \(S\) 中把所有 \(T\) 出现的段都标记出来。如果 \(S\) 中的每个下标都被标记过,称 \(T\) 可以密铺 \(S\)
  现在给出一个串 \(S(|S| \leq 2 \times 10^5)\),对于它的每一个前缀,都要求能密铺它的最短的串的长度。
  题解:还是一道比较精巧的字符串题。
  分析一下后会发现,用来密铺的小串 \(T\),也必须是 \(S\) 的前缀。
  考虑如何计算答案。如果我们枚举了一个前缀 \(T\)(用它来作为小串),并找出了它在原串中所有出现的位置。那么能被它密铺的前缀 \(pre_i\) 需满足两个要求:① \(i\) 的位置必须小于等于 \(T\) 极远能密铺到的位置 \(p\);②S[i-|T|+1..i]=T。
  假设对于每一个前缀 \(T\),我们求出了它能密铺的极远距离 \(R_T\)。为了满足第二个条件,对 \(S\) 建立 \(kmp\) 树,这样能密铺 \(pre_i\) 的备选小串,必然是其到根路径上的串。我们只需在其中找一个深度最浅(这样长度就最小)的\(R_T \geq i\)\(T\) 即可。这一步只需一个 \(set\)
  那么如何预处理 \(R\) 数组呢?首先,我们可以用 \(ex-kmp\) 或 哈希 预处理出 \(lcp_i\) (后缀 \(i\) 和原串的 \(lcp\))。枚举 \(T\) 时,关注所有 \(lcp_i \geq |T|\)\(i\),它们是合法的 \(T\) 覆盖的开头。如果从小到大枚举 \(T\),相当于每次会删掉一些 \(i\),然后问“断层”最早出现在哪里。形式化的来说,对于还合法的位置集合 \(i\),求一个最小的相邻的 \(pair\),使得 \(i_2-i_1 > |T|\)。我们可以用线段树来维护这个需求。把所有合法的 \(i\) 看做是 \(1\),在线段树底层记录它和下一个 \(1\) 的距离。如果维护了区间最大值,询问时直接在线段树上二分。删除 \(i\) 也能方便地维护,总复杂度为 \(O(N \log N)\)
  其实还存在一个更美妙的做法。每次枚举 \(T\) 后,我们直接尝试去密铺!铺完第一段(一定是开头)后,我们找到这一段里最靠右的合法起点继续铺。可以证明,铺完的复杂度是 \(O(\frac{N}{|T|})\),因为第一段、第三段、第五段……肯定不会重叠。全部枚举完后就是一个调和级数。找最靠右的位置可用树状数组或并查集,总复杂度为 \(O(N \log^2 N)\)\(O(N \log N \alpha N)\)

T117-2018 ICPC - Asia Jiaozuo J

  题意:考虑一个 \(M \times M (\times 1500)\) 的网格和在上面的 \(N(3 \times 10^5)\) 个矩形。现在要删掉正好两个矩形,使得至少被一个矩形覆盖的格子个数变得尽量得少。
  题解:假设我们能预处理出,哪些格子只被一个矩形覆盖(称为 \(A\) 类点),哪些被两个矩形覆盖(称为 \(B\) 类点),以及对应矩形的编号。那么只要枚举所有 \(B\) 类点,假设删的是它对应的两个矩形 \(x\)\(y\)。答案为:只被 \(x\) 覆盖的 \(A\) 类点数 + 只被 \(y\) 覆盖的 \(A\) 类点数 + \(x\)\(y\) 交的矩形中的 \(B\) 类点数。
  难点在于预处理,需要不带 \(log\) 的实现。如果不需要知道对应矩形编号,每次只要矩阵加即可(打一下差分标记即可做到线性)。
  先考虑维护所有 \(A\) 类点的对应矩形,其实很简单。对于第 \(i\) 个矩形,我们只需把它包含的格点全部加上 \(i\)。最后,如果一个点是 \(A\) 类点,它上面的值即为对应矩形编号。
  对于 \(B\) 类点的预处理也可以使用类似的方法。为每个矩形定两个值 \((u_i,v_i)\),再定义两种运算 \(\oplus_1,\oplus_2\),且它们满足交换律。对于 \(u\)\(v\) 要开两个不同的二维数组,每次对矩形内部进行 \(\oplus\) 运算。最终对于每个 \(B\) 类点,我们希望根据它的 \(\sum u,\sum v\)信息,可以唯一地还原出对应的两个矩形 \(i\)\(j\)。比如,我们可以设 \(\oplus_1=\oplus_2=+,u_i=i,v_i=i^2\)。最终总复杂度为 \(O(M^2)\)

T118-2018 ICPC NEERC I

  题意:在一个长度为 \(N\) 的排列中,如果存在一个区间 \([i,j]\),使 \(\max(a_i,\dots,a_j)-min(a_i,\dots,a_j)=j-i\)(且区间长度不为 \(1\)\(N\)),那我们称之为 \(interval\)。如果一个排列不存在 \(interval\),我们称之为 \(interval-free\)。求长度为 \(N(N \leq 400)\) 的所有 \(interval-free\) 的排列个数,对大质数取模。
  题解:这道数数题很精妙啊!首先,如果两个 \(interval\) 有交,它们的并必然也是 \(interval\)。这启发我们去极大化所有 \(interval\) 再计数。注意:在分析时我们认为,长度为 \(1\) 的区间也算 \(interval\)
  由上面分析,我们必然能将一个排列划分成若干个不相交的极大的 \(interval\)。当然,这是存在一个反例的:如果只有两个极大的 \(interval\),它们是可以相交的(因为此时它们的 \(union\) 是全局,我们不认为这是一个 \(interval\))。
  所以我们将分两次动态规划。第一次是求出由两个极大 \(interval\) 组成的排列数(注意它们可以相交);第二次是求出至少有三个\(interval\) 顺次连接起来的排列数。从 \(N!\) 里减去这两部分的答案即为所求。
  对于第一个问题,我们先考虑左边 \(interval\) 值小于右边 \(interval\) 的情况,最后乘 \(2\) 即可。因为交会带来麻烦,我们不妨强制右区间极长(为 \([k+1,N]\)),那么左 \(interval\) 相应地缩小为 \([1,k]\)。即:不存在更小的 \(k\),使得 \(k\) 也满足这种划分。
  现在,设 \(G_N\) 表示长度为 \(N\) 的排列中,不存在这种 \(k\) 划分的排列数。考虑用容斥计算,枚举一个它的一个最小违法划分 \(k\),并调用子函数来强制它就是最小划分。即 \(G_N=N!-\sum_{k=1}^{N-1} G_k \times (N-k)!\)
  当段数大于等于 \(3\) 时,因为区间严格不相交,其实更好算。核心思想就是:设原题数列的答案为 \(F_N\),每次枚举几段,把排列放进去,再用 \(F_N\) 去强制它们不会形成更大的 \(interval\)
  最后我们得到,\(F_N=N!-2\sum_{k=1}^{N-1} G_k \times (N-k)!-\sum_{k=3}^{N-1} C_N^k F_k\)。其中 \(C_N^k\) 可以预处理,表示将 \(N\) 个数划成 \(k\) 个排列(彼此也有顺序)的方案数。
  

T118-2018 ICPC NEERC D

  题意:给出一个 \(N(N \leq 10^5)\) 个点和 \(M(N-1 \leq M \leq N+42)\) 条边的无向图。求 \(\sum_{i=1}^N \sum_{j=i+1}^N d_{i,j}\)
  一个很好的用来解决 \(N-1 \leq M \leq N+K\) 这类问题的方法:每次选择一个度数为 \(1\) 的点将其删掉,剩下的图里度数大于 \(2\) 的点不会超过 \(2K\)。因为每次删点后,边与点的差都不会变。所以删完后,\(\sum d_i=2(n+K) \leq 2n+2K\)
  此题中,每次删除叶子 \(x\) 的时候,可以直接加上 \(n-1\),然后把 \(x\) “附” 在父亲 \(y\) 上。即我们把问题更一般化,每个点还有一个权重 \(w_x\),我们要求的是 \(\sum \sum w_x w_y d(x,y)\)
  新题中,我们称度数超过 \(2\) 的点为关键点(它们不超过84个)。关键点到别的点的最短路可以暴力算。
  我们算的是以每个起点开始的值,所以最后答案除2即可。
  观察到,剩下的点都成为了一条条“链”连接上两个关键点。暴力枚举每一条链,先预处理出链上的点的一些信息。然后枚举不在该链上的每一个非关键点 \(i\)(注意:每多一条链,边都要比点多耗一条,所以链的总数也是 \(O(K)\)),\(O(1)\) 计算出 \(i\) 到这条链上的所有点的答案(发现只需维护知道链上 \(w_i\),\(w_i \times i\)的前缀和即可算出)。至于同一条链上两两不同的点的答案,也可以在预处理后讨论出来。总复杂度 \(O(NK)\)

T119-2018 ICPC NWERC A

  题意:给出平面上的 \(N(\leq 10^5)\) 个点对 \((x_i,y_i)\)。构造对应的 \(N\) 个点对 \((x'_i,y'_i)\),满足 \(x'_i \leq x'_{i+1},y'_i \leq y'_{i+1}\),且 \(\sum (x_i-x'_i)^2+(y_i-y'_i)^2\) 最小。
  题解:一个显然的结论是:\(x\)\(y\) 两维独立,可以分开做。
  现在要解决的子问题是:给出数轴上 \(N\) 个点 \(a_i\),构造对应的 \(b_i(b_i \leq b_{i+1})\),使得 \(\sum (a_i-b_i)^2\) 最小。
  对于只有前 \(k\) 个点的子问题,假设我们找到了最优的 \(m\) 个位置 \(x_1,x_2,\dots,x_m\),其中每个位置选了\(c_i\) 个点(所以 \(\sum x_i = k\))。
  现在我们考虑第 \(k+1\) 个点放在哪里。 如果 \(x_m \leq b_{k+1}\),直接把 \(b_{k+1}\) 设为 \(x_{m+1}\) 即可。不然的话,\(x_m\) 可能需要移动。一个很显然的结论是,\(x_m\)\(b_{k+1}\) 这些位置会合并在一起。假设新的最优位置是 \(x\),我们要极小化 \(\sum \limits_{k-c_{m}+1}^{k+1} (x-a_i)^2\)。由二次函数的性质,\(x\) 应该取 \(a_{k-c_m+1} \sim a_{k+1}\)的平均值。所以我们把 \(b_m\) 设为 \(x\),扩大 \(c_m\)。注意到可能会继续往前合并。
  事实上,我们维护出来的就是 \(a_i\) 一段一段非递减的平均数。
  有关“集合平均数”的题还有很多,比如CCPC2018 桂林站的A题。我们来看一道它的拓展版:POJ2054。
  给出一棵 \(N(\leq 1000)\) 个点的带点权的树,将所有点安排进一个数组,最小化 \(\sum v_i \times rk_i\) 。一个点必须排在它的父亲的后面。
  设权值最大的点是\(b\)。如果没有限制,它必然排在第一个;那么有限制的条件下,它一定紧跟在它父亲 \(a\) 后面。再考虑,如果 \(a\)\(c\) 此时同时可以放,应该选择 \(abc\) 还是 \(cab\)。暴力推式子后可以发现,比较函数即为 \(\frac{v_a+v_b}{2}\)\(v_c\)。基于这两点,可以视为 \(ab\) 完全合成了一个新的“大点”,大点的值取两者的平均值。一直重复这样的操作即可(直到整棵树只剩下了一个点)。

T120- Petrozavodsk Summer 2015 - Yandex Cup Stage 1 G

  题意:给出有 \(N=2^k(k \leq 17)\) 个数的数组 \(a_i\)。定义数组 \(b_i\) 为:\(b_{i,j}=a_j \oplus i\)。将这 \(N\) 个数组按字典序排序(一样就按编号排),输出最后的排列结果(编号)。多组数据。
  做法挺巧妙的。有一个关键的性质是:\(b_{i,0 \sim 2^{k+1}-1}\)这些数字是可以被 \(b_{i,0 \sim 2^k-1}\)\(b_{i \oplus 2^k,0 \sim 2^k-1}\) 顺次连接表示。这样我们就可以类似后缀排序一样做了:先按 \(b{i,0}\) 对每一个数组重分配权值,每次利用上一次结果的两段进行两次基数排序。

T121-BSUIR Open Finals 2015 A,H

  题解:待更。

T122-XV Open Cup - Grand Prix of Central Europe (AMPPZ-2014) I

  题意:有 \(N\) 个士兵,士兵 \(i\) 拿着枪指向士兵 \(p_i\),且 \(p_i\) 是一个排列。再给出 \(t_i\),表示士兵 \(i\) 的开枪时间(显然,当一个士兵死亡后,他就不能开枪了)。求最后会有几个士兵活着。有 \(Q\) 个询问,每次永久地修改一个 \(t_i\)。为防止歧义,保证任意时刻的 \(t_i\) 互不相同。
  题解:先考虑链怎么做。设 \(f_i\) 表示第 \(i\) 个人的死亡时间,从前往后dp。若 \(f_i < t_i\),则 \(f_{i+1}=\infty\);否则 \(f_{i+1}=t_i\)
  仔细观察这个结构,\(f_{i+1}\) 的取值其实只有两个,而且只取决于 \(f_i\)(因为 \(t_i\) 已经固定)。我们用线段树来维护这一结构。对于每个区间 \([l,r]\),分别维护 \(f_{l-1}\) 是否是 \(\infty\) 时,这个区间的存活人数以及最后一个人的 \(f_i\)。这显然是可以合并的,而且支持快速改一个人的 \(t_i\)
  至于环,每次找到环上最小的 \(t_i\)切开就能变成链了。实际做的时候倍长一下维护得多一点就行。

T122-XV Open Cup - Grand Prix of Central Europe (AMPPZ-2014) J

  题意:有 \(N(\leq 10^5)\) 个点的一棵树,要在树上选一个点 \(x\) 当做根。有 \(M\) 个限制 \((x,y,d)\),表示 \(x\)\((x,y)\) 这条链的距离必须小于等于 \(d\)。找出一个合法的 \(x\) 或输出无解。
  题解:核心思想是,对于所有限制,充要地在树上打上标记。然后从根开始 DFS 走,看看能否走到一个标记合法的点。
  对于一个限制 \((x,y,d)\),设它们的LCA是 \(z\)。对于\(x\)\(y\) 这两个点,我们打一个标记:往子树里走,步数上界是 \(d\);对于 \(z-x\)\(z-y\) 这两条链上的每一条边,我们想要打一个标记:如果走的不是这条边(开始远离链),要求走出去的步数上界是 \(d\)(这里可以用树链剖分来维护)。点 \(z\) 的限制稍微特殊一些:如果走的不是到 \(x\) 或者到 \(y\) 的这两条边,走出去步数上界是 \(d\)。对于 \(z\) 之上的点,分为上界和下界两种:下界指的是,从根开始至少需要走 \(deep_z-d\) 步(所以这个限制直接打在根上即可);上界是,对于 \(z\) 到根的任意一个点 \(t\),如果 \(t\) 不往 \(z\) 方向走,有一个 \(d-(deep_z-deep_t)\) 的上界。注意到,在这个描述中,限制量随着点变化,维护困难;反过来维护,先在点 \(z\) 处打一个固定标记,最后DFS时,每到一个 \(t\),就查询一下 \(t\) 子树的限制。
  限制加完后一路DFS下去,每次都要求下界小于等于上界,一旦下界削减为 \(0\),说明当前这个点合法。
  比赛时做复杂了,因为此题无需求出每个点的合法性,只需求出一个合法解。考虑现在有一个待定的点 \(t\),注意到,如果它不满足限制 \(i\),在它没到 \((x_i,y_i)\) 的链上时,调整方向是唯一的。这样做法很简单,开始时随便选一个初始点 \(t\),每次进来一条链,如果 \(t\) 不满足要求,就暴力朝链的方向移动到正好满足要求的新的点 \(t'\)。最后重新check一遍所有限制即可。

T123-XV Open Cup - Grand Prix of SPb C

  题意:给出一个 \(N(\leq 10^5)\) 个点的无向图,每个点的度数不超过 \(5\)。要用三种颜色对点染色,使得对于每个点,最多有一个邻居颜色和它一样。
  题解:看上去很像一道 NP Hard 的题?首先会注意到一个性质:根据鸽笼原理,每次我们总能调整好一个点,使其满足限制(直接找邻居中出现颜色最少的给它就行;反证,如果每种颜色 \(\geq 2\),度数至少为 \(6\),与条件矛盾)。但是要注意,它周围的点可能会因此不满足限制。
  现在我们用一种看上去很 naive 的调整法。初始给每个点一种随机的颜色;每次找到图中不合法的点,调整它,然后继续迭代。证明其实很简单:考虑所有两端同色的边。每次调整时,至少减掉 \(2\) 对同色边,最多加上一条同色边。所以做 \(O(N)\) 次必然能停止。

T123-XV Open Cup - Grand Prix of SPb G

  题意:有一个 \(N \times M(16 \leq N,M \leq 25)\) 的格子,开始都是白色。电脑和你轮流操作,每次选择一个 \(2 \times 2\) 的白色块将其染成黑色,不能染的时候就输了。电脑的策略是,每次随机一个可以涂的位置涂成黑色。现在你要和电脑交互玩 \(300\) 盘,最多只能输 \(10\) 盘。
  题解:数据范围太大乐,刚开始只能随机地和它下。下到一个残局后(每个连通块都比较小时),我们就暴力求 \(sg\),借此来必胜。
  想法很简单,细节处理起来却很麻烦。首先是对于一个连通块,如何定义小,且如何记录状态来算 \(sg\)?我采用的做法是,找到它中间所有可以染的块,若块数 \(\leq K\) 则认为是“小”的。对此,设计一个最坏情况是 \(2^K\) 的动态规划:设 \(S\) 表示已经涂过了 \(S\) 表示的这些块,剩下的东西的 \(sg\) 值是多少。注意到,状态数严格不满,实际是不会跑到底层的。
  实测在空间和时间允许的情况下,\(K\) 最多能取 \(19\)。此时,若读入的 \(N,M\) 比较小(如 \(\leq 20\)),平均胜率也就刚好 \(290/300\),那么最坏情况显然是过不了的。注意到,胜率的瓶颈在于:我们第一次跑暴力时,\(sg=0\),且电脑每次正好按着必胜的策略走。可以稍微加一些 \(trick\),比如,如果我这次下完随机的一步后就能暴力 \(sg\) 了,那么我多次(实测取 \(4 \sim 5\) 次,取多了会超时)随机这一步,直到剩下的图丢给对方时 \(sg=0\) 了为止。因为数据都可以本地测试,还可以对各种点进行针对性的优化,最后就能稳定过了。

T127-Petrozavodsk Winter 2014 - Jagiellonian U Contest J

  题意:有一只虫子,一开始只有一节,节上没有脚。每一节每一秒钟可以有三种操作:①不变;②分裂成两节(脚随意分配);③长一只脚。给出虫子现在的样子:有 \(N(\leq 5 \times 10^6)\) 节,每节 \(a_i\) 只脚。问最快能几秒达到这个状态。
  题解:一个性质:一定是先分裂最后再长脚。逆回去考虑问题,可以得到一个暴力做法:每秒钟,如果一节上有脚,脚的数量减一;如果有连续的两节没有脚,可以将它们合成一节;问变成一节零脚的秒数。
  题目要求只能线性。考虑每次按最大值分治(用笛卡尔树 \(O(N)\) 实现)。对于区间最大值 \(v_i\),前 \(v_i\) 秒钟它还没变 \(0\),所以左右两边问题独立;\(v_i\) 秒后,左右两侧肯定都只剩下 \(0\) 了。因此可以设 \(solve(S)\) 表示:过了 \(S\) 中最大值这样的秒数后,最少还剩下几个 \(0\)。每次递归左右两边后,这些 \(0\) 还有 \(v_i-v_{left/right}\) 秒可以合并。可以用对 \(2\) 的幂次上取整快速求出合并完后 \(0\) 的个数,加起来即可。

T128-Petrozavodsk Summer 2011 - Warsaw U Contest D

  题意:给出一张 \(N(\leq 1000)\) 个点和 \(M(\leq 100000)\) 条有向边的无权图。有 \(Q(\leq 200000)\) 个询问,每次要不永久删掉一条边,要不询问 \(1\) 号点到 \(x\) 号点的最短距离。
  题解:这是一道很灵巧的题。重点关注 \(N=1000\),以及边不带权
  我们必须以某种形式实时维护好到所有点的最短路。即使反过来一一加边,也很难维护这个结构。转化思路,设 \(dp_{i,j}\) 表示从点 \(1\) 开始走最多 \(i\) 步走到 \(j\) 后,经过的最早删除的边最晚是多少。这可以通过 \(NM\) 的DP预处理。容易发现,\(dp_{i,j}\) 是有单调性的;所以在询问的时候,只需二分答案,在dp数组上check即可。

T128-Petrozavodsk Summer 2011 - Warsaw U Contest G

  题意:有一张 \(N(\leq 3000)\) 个点的无向图,保证 \(N\)\(3\) 的倍数,且至少有 \(\frac{2}{3}N\) 个点彼此构成一个团。要求找到正好 \(\frac{1}{3}N\) 个点,使得它们彼此是团。
  题解:最大团是NP问题,必然根据性质来做。本题容易往最大独立集上靠。可惜的是,最大独立集没有 \(k\)-近似做法。
  考虑一个很 \(simple\) 的过程:开始假设所有点都是合法的。每次随意取两个彼此没有边但都合法的点,同时把它们标为不合法。性质:最后剩下的 \(\frac{1}{3}N\) 个点必然是答案。证明很简单,每次删点时,不可能同时删除 \(\frac{2}{3}N\) 团里的点。那么迭代了 \(\frac{1}{3}N\) 轮后,最坏情况也剩下了团。

T128-Petrozavodsk Summer 2011 - Warsaw U Contest J

  题意:给出一棵 \(N(\leq 100000)\) 个点的边带权的树。假设有 \(k\) 个叶子,要求选 \(\lfloor \frac{k}{2} \rfloor\) 组叶子,求它们两两距离和最大和最小分别能是多少。
  题解:下取整比较恶心,不妨先假设 \(K\) 是偶数。所有叶子必然都被选,而每组 \((x,y)\) 的距离是 \(dis_x+dis_y-2dis_{lca(x,y)}\)。求最小直接贪心即可,为了让lca尽量的深,每次能合并就合并,最多有一条链往根走。
  求最大的话,需要用到一个经典的性质:可以直接考虑每一条边 \((x,y)\) 的贡献,它的贡献是 \(\min(size_x,leaf-size_x)\) (\(size_x\)\(x\) 子树里叶子的数量)。证明也很简单。显然这个min是一个必要条件。考虑每次按这条边分治,min处的点一定朝另一侧匹配;而匹配出去后,这些点具体和谁匹配都无关紧要;可以视为每次断开这条边,两边问题独立;一直迭代下去必然能找到合法方案。
  现在可能会有一个叶子不参与匹配。在原来的基础上加一维来dp。设 \(f_{x,0}\) 表示 \(x\) 里所有叶子都参与匹配,\(f_{x,1}\) 表示有一个叶子不参与匹配。 \(f_{x,1}\) 可以通过左右前缀和来计算,或者更方便的,每次用 \(f_{x,0}+f_{y,1} / f_{x,1}+f_{y,0}\) 来更新。

T129-XV Open Cup - Grand Prix of Siberia J

  题意:给出平面直角坐标系里的 \(A,B,O\) 三个整点。从 \(A\) 走一条弧线到 \(B\),要求对于弧上每个点满足,该点关于弧的切线方向和该点指向 \(O\) 的方向的夹角为定值。求最短弧长。
  题解等角螺线:螺旋向圆心的弧线,且任意一条原点开始的直线与其的夹角为定值。其极坐标方程为 \(r(\theta)=ae^{b \theta}\)
  容易发现,此题走的弧线就是等角螺线。妨假设 \(OA\) 长度更长,把 \(OA\) 作为极坐标的 \(\theta\) 起点,根据 \(B\) 的位置解出极坐标方程,并通过积分 \(L=\int_{\theta_1}^{\theta_2} \sqrt{r^2(\theta)+r'^2(\theta)}\) 计算弧线长度。注意要特判 \(OA=OB\) 以及 \(O,A,B\) 共线的情况。

T129-Petrozavodsk Winter 2014 - U of Latvia Contest G

  题意:考虑一个 \(K\) 层的塔,第 \(i\) 层正好要放 \(i\) 个球。现在有三种颜色的球各 \(R,G,B(<2^{31})\) 个,把它们正好放满这几层,且每一层必须放颜色相同的球。打印一种放置方案或输出无解。
  题解:如果放两种颜色的球,只需对其中一种进行适配(从大到小枚举层,能放就放),剩下的放另一种即可。
  三种则比较一般性,背包向问题权值大时无解,考虑乱搞。观察到,相邻层权值相近。我们知道,\(1,2,4,\dots\) 的序列就能贪心从大到小放,那么这里的结构是不是更强了一点呢?具体地,我们想利用这种“充足的可调整性”来解决问题。
  DP发现,当 \(K=40\)时,对于所有 \(R+G+B=\frac{(K+1) \times K}{2}\) 的方案,只有当有两个 \(1\) 和两个 \(2\) 时无解(显然),别的都有解!所以一种可行的做法时,当 \(K>40\) 时,每次放数量最多的球,等到 \(40\) 时直接调用结果。

T129-Petrozavodsk Winter 2014 - U of Latvia Contest C

  题意:将 \(1 \sim K\) 顺次在纸上写 \(M\) 遍。将数字每隔 \(N\) 个划成一个大段(最后可能会多出不完整的一段)。问有多少大段包含了至少一个完整的 \(1 \dots K\)\(N,K \times M \leq 10^{19}\)
  题解:先特判最后一段并去掉。显然,当 \(N \geq 2K-1\) 时,每一大段都合法。现在只考虑 \(K < N < 2K-1\) 的情况。
  设现在有 \(X\) 个大段,那么有 \(\lceil \frac{XN}{k} \rceil\)\(1 \sim K\) 的小段涉及到。有多少大段合法,等价于有多少小段被完全包含(因为一个合法大段仅会完全包含一个小段)。而统计小段时,再用容斥,去算有多少不合法的小段。
  不合法的小段一定是“穿过”两个大段的。一共有 \(X\) 个大段,显然有 \(X\) 个结尾处。每个结尾处必然对应一个不合法的小段,除非那里正好也是小段的交界处。所以不合法小段数量是 \(X-X/T\) 个。\(T\) 是每隔几个大段会出现大小段同时结尾。\(TN \mod K =0\),所以 \(T=K/(N,K)\)

T129-Petrozavodsk Winter 2014 - U of Latvia Contest J

  题意内存很小。有 \(N\) 个物品依次排成一行,每一个货物重量 \(a_i(1 \leq a_i \leq T)\),还有一个总载重 \(T(\leq 10^9)\) 的运输机。每次可以从头或者尾选货物,选出若干后,如果它们的的总重量 \(\leq T\),就可以被运输机一次性运走。问最少运几趟可以把所有货物都运走。
  题解:显然是个区间DP的问题。很容易思维僵化,设 \(f_{i,j}\) 表示运完 \(i \sim j\) 这一段最少需要几趟。转移时每次枚举第一次运输时左端点结束点 \(x\),通过单调性找到右端点起始点 \(y\)(满足 \(\sum_{k=i}^p a_i+\sum_{k=q}^j a_i \leq T\))并转移。复杂度为 \(O(N^3)\)
  注意上述DP是区间转移的,而此题也可以做到单点转移。有个经典做法是,设代价 \(S=(X,Y)\) 表示已经运了 \(X\) 趟,且最后一趟还能载多载总重为 \(Y\) 的物品。显然 \(S\) 具有偏序性。我们在DP时可以直接记录区间 \(S\) 的最优值,每次枚举放左边的点或者右边的点,复杂度为 \(O(N^2)\)
  如果优先按长度区间DP,转移长度为 \(L\) 的DP数组时,只需用到 \(L-1\) 的结果,所以可以直接滚存,空间复杂度为 \(O(N)\)
  注意:还有另一种DP设计方法:设 \(f_{i,j}\) 表示搬完 \(i \sim j\) 之外的物品的最优状态 \(S\)。此题中两种设法均可。

posted @ 2018-12-02 20:48  了491  阅读(666)  评论(0编辑  收藏  举报