zoukankan      html  css  js  c++  java
  • 2019字节跳动ACM程序设计冬令营题解

    喜欢这张图~

    day1

    【E√,F√,G√,L√】

      水题/老套路题。

    【B,H,I】

      待补。

    【A√】

      题意:有 (k(leq 1000)) 个选手和 (N(leq 1000)) 个评委。每个评委给出一个长度为 (k) 的排列,表示对每个选手的喜欢程度。选手的最终名次是这么决定的:从 (1) 号评委开始,每次当前评委选取最厌恶的(且名次待定的)选手,将其设为名次待定选手中的最后一名。如果 (n<k),评委循环决策,直到确定了所有选手的名次。现在你是 (v) 号评委,只有你还未给出排列。你关注 (k) 号选手。现在你能任意设定排列,求 (k) 号选手最终排名最好能是多少。
      题解:先假设没有评委 (v) 模拟一遍,确定出依次被确定出的选手编号(轮到第 (v) 号评委时用 (o) 表示): (xxxxoxxxxoxxyxoxxdots)。设 (y) 表示 (k) 的位置。现在我们要找一些选手将它们填到 (o) 里,使得 (y) 的位置尽量靠后。首先,优先放 (y) 之后的所有选手,因为这样 (y) 的排名不发生变化。如果还有空格需要填 (y),此时我们会发现,无论把哪个数字提前,(y) 的位置必然会前进。而如果我们每次把 (y) 之前的那个数提上去,(y) 的位置必然前进 (1) ——即这必然是最优解。所以确定 (v) 号评委排列时,我们只需先把 (x) 后面的数字塞进去,随后把 (x) 前面的数字逆序塞进去。

    【C√】

      题意:给出一个长度小于 (5000) 的字符串。将其所有子串排序并连接。有 (M(leq 5000)) 个询问,每次问新串第 (k) 位的字符是什么。
      题解:构出后缀自动机直接遍历的复杂度是 (O(N^2 sum)) 的,不太优美。
      观察 (height) 数组。假设我们在考虑 (l sim r) 这些排名的后缀。设 (L=min(ht[l+1] dots h[r])),容易发现,长度为 (1,2,dots,L) 的前缀必然依次排布在新串开头,且各有 (r-l+1) 个。对于长度更长的子串,我们可以把((l,r)) 分成两半,这两半字典序严格递增。现在问题独立,先递归前一半再递归后一半。单次询问复杂度 (O(|S|)),总复杂度 (O(|S|^2+M|S|))

    【D√】

      题意:给出一个长度小于 (3000) 的字符串,求有多少种划分方案,使得每一段字典序都是严格递增的。
      题解:有个经典操作是,设 (diff_{i,j}) 表示后缀 (i) 和后缀 (j) 的第一个不同位置,这个可以递推预处理出。倒着dp,设 (f_{i,j}) 表示后缀 (i) 的划分里,第一段是 (S_{i sim j}) 的方案数。转移时枚举 (k),把合法的 (f_{j+1,j}) 累加进答案。显然 (k) 是有单调性的,可直接根据 (diff_{i,j}) 计算出来,再套个前缀和优化即可。

    【J√】

      题意:给出两棵 (2N-2(N leq 1000)) 个点的树,保证每个点度数是 (1)(3),且叶节点编号为 (1 sim N)。问有多少对四元组 ((A,B;C,D)),满足 (A,B,C,D) 是叶子,且第一棵树上 (A sim B)(C sim D) 的有交性和第二棵树上相反。
      题解:转化成:求在两棵树上都不交的四元组个数。考虑枚举 ((A,B))(LCA) 统计个数。因为我们在无根树上考虑问题,要拓展这个 (LCA) 的“定义”。严格地来说,对于一组合法的 ((A,B,C,D)),定义 (x)(A sim B) 路径上里路径 (C sim D) 最近的点。我们每次枚举第一棵树上的 (x) 和第二棵树上的 (x) 并统计答案。容易发现,每个合法四元组会被统计两次。
      每次枚举度数为 (3) 的点。其中两个度分别放 (A)(B),另一侧放 ((C,D))(只需统计点的个数 (t),方案数就是 (C_t^2))。我们可以借助有根树的 (DFS) 序快速维护答案。因为有两棵树,可行点数是它们的交。这是一个经典问题,对于一个点 (x),假设它在两棵树上的 DFS 序是 ((u_x,v_x)),将其看做一个点,每次就是矩形询问。因为是离线的,我们可以二维前缀和预处理,就支持 (O(1)) 询问啦。
      还有一种直接 DP 的做法:我们枚举第一棵树 ((A,B)) 的 LCA。将第一个分叉的所有叶子在第二棵树的对应位置标为 (1),第二个分叉标为 (2),第三个分叉标为 (3)。对于第二棵树里的所有从 (1)(2) 的路径,它将该树化成了若干个连通块,我们要求每个联通块 (C_X^2) 的和。这可以通过比较麻烦的树形 DP (O(N)) 求出来。总复杂度也是 (O(N^2))

    【K√】

      题意:有一个 (N imes N(N leq 300)) 的数字矩阵。求一个子矩阵,使得 “数字和” 比上 “周长” 最大。
      题解:直接做是 (N^3 log V) 的:枚举上下边界后分数规划。有一个小 trick是:每次做到一组上下边界时,先去 check 一下当前答案,如果不合法直接退出二分过程。这个做法的理论复杂度是 (O(N^3+N^2 log V)) 的。
      上述证明可以抽象成这么一个问题。我们有 (N^2) 个箱子,每个箱子可以 (O(N log V)) 确定它的解,或者 (O(N)) 验证一组解可不可行。现在要求所有箱子解的最大值。考虑一种做法:每次随机选择一个箱子确定它的最优解 (X)。然后遍历所有箱子 (O(N)) check,如果 (X) 不是该箱子的解就扔掉这个箱子。对于剩下的箱子继续这么做。这样的复杂度是 (T(M)=N log V+MN+T(x)),其中 (x)(0 sim M) 里随机的。事实上,这个复杂度等于 (T(M)=N log V+MN+T(frac{N}{2}))

    day2

    【A,F,H,I】

      不补了。

    【B√】

      题意:有 (N(leq 100000)) 个物品,每个物品有两维 ((p_i,q_i))。现在最多可以用两次 (split) 操作。每次选择一个物品和一个常数 (p(0 < p < 1)),将物品按 (p) 等比例拆成两个。操作完后,要将物品分成两堆,每堆两维的和都彼此相同。
      题解:先考虑一维怎么做。将物品看成线段,整齐地铺在数轴上。我们在 (frac{sumL}{2}) 处切一刀,切到的那个物品需要被 (split) 一次。
      两维需要一点小技巧。将每个物品看做一个底边为 (p_i),高为 (frac{q_i}{p_i}) 的长方形。我们需要在 (X)(X+frac{sum p_i}{2}) 处切,使得中间那一块长方形的面积和是总面积的一半。如果我们按照 (frac{q_i}{p_i}) 将长方形排序,那么切出来的面积和切的位置 (X) 是正相关的。二分即可,复杂度 (O(N log V));也可以单调地扫描过去,每次解一个二次方程,复杂度 (O(N log N))

    【C√】

      题意:考虑正 (N(leq 5 imes 10^5)) 边形上的 (N) 个点。将它们构成一个边权只有 (0/1) 的完全图。读入 (M) 条边,剩下的所有边的颜色是根据一个参入读入的函数构造的。现在要构造一个生成树,要求每条边颜色必须相同,且这些边在正 (N) 边形内不能相交。
      题解:最后一个限制很难,反而在暗示,存在一种很简单的构造方法。我们先考虑 (N) 条环边,如果颜色全一样,显然我们直接得到了一组解(去掉任意一条边即可)。否则,必然存在一个点 (x),它左右的边颜色不同。假设它相邻的两个点是 ((u,v)),我们先删掉 (x),连上 ((u,v)),递归地构造出 (N-1) 个点的生成树。最后根据生成树颜色的黑白性,再连上和 (x) 相连的边即可。递归到剩下 (2) 个点时必然合法。用 (map) 简单维护,总复杂度 (O(N log N))

    【D√】

      题意:给出一个 (N) 个点的简单多边形。对于一个定点 ((x0,y0),随机枚举一条穿过它的直线。求与多边形交的长度和的期望。
      题解:有一个令人惊讶的性质是:就像有向线段计算面积一样,计算长度和也是可以每条有向边独立的。对于每条有向边,积分式是形如 (int frac{1}{cos( heta)}) 或是 (int frac{1}{sin( heta)})。上下同乘一个分母即可化为多项式积分。总复杂度 (O(N))

    【E√】

      题意:给出一个字符串集合 (S_1,dots,S_n)。要求合法的字符串集合 (T_j) 的个数,使得每一个 (S_i) 能且仅能找到一个 (j) 使得 (T_j)(S_i) 的前缀。同时规定了集合大小是 (M)((|S_i| leq 200,N,M leq 2000))
      题解:建出 (S_i)(trie) 树。相当于是要在树上选择 (M) 个互不相同的点,使得每个叶子仅属于一个点的子树。设 (dp_{i,j}) 表示决策完了 DFS序 第 (i) 个叶子,且总共选了 (j) 个点的方案数。如何选当前点?暴力枚举 (j) 的祖先 (x),如果(R_x=j),那么可以从 (f_{L_x-1,j-1}) 转移过来。注意到,暴力跳父亲直到不合法的总复杂度是 (O(VM)) 的((V) 是总点数),因为一个点 (x) 只会被 (R_x=j) 的点跳到。因为 (V) 可以很大,可以建出 (N) 个点的虚树,将一条链上的点压成一个。

    【G√】

      题意:在一棵 (N(leq 10000)) 个点的树上选择最多 (K(leq 100)) 条点不相交的路径,求路径上点数之和的最大值,并输出一种端点的方案。
      题解:设 (f_{x,y,0/1}) 表示 (x) 子树里选了 (y) 条链,且是否有一条链向上顶 的点数和的最大值。每次在子树里 (dp) 时,是可能把两条路径并在一起的,所以转移时要设 (G_{i,y,0/1/2}) 表示做到第 (i) 个儿子,选了 (y) 条链,且总共有 (0/1/2) 三条支链向上顶的点数和的最大值。
      在子树一个个dp过去的时候,再开一个数组记录一下对应方案即可还原。把 (y) 限制成子树 (size),复杂度就是 (O(NK)) 了。题解的证明方法比较帅,分别考虑 (size) 大于 (K) 的和不大于 (K) 的两部分,复杂度都是 (O(NK))

    【J√】

      题意:定义 (F(N)) 为:小于 (N) 且与 (N) 互质的数的和。设 (M=F(N)),给出 (M),求一个合法的 (N)(1000) 组数据,(M leq 10^18)
      题解:(F(N)=prod p_i^{2k_i-1} imes (p_i-1))。如果我们能快速分解出 (M),直接枚举选择了哪些 (p_i),然后 (O(log M)) 确认即可。
      直接跑 rho 太慢了。考虑先预处理出前 (10^6) 的质数。对 (M) 筛后,最多只会出现 (M'=P)(M'=p^2)(M'=PQ) 三种形式。前两种都可以特判,终点考虑第三种。推理一下可知,(10^6<P<Q<10^9),且(Q) 这个质数必然出现在 (p_i) 里,所以 (P) 必然不出现。因为 (P|(Q-1)),我们可以直接枚举 (frac{Q-1}{P}) 的值 check 即可,每次只要枚举到 (1000)

    【K√】

      题意:给出 (N(leq 250)) 个点,保证没有三点贡献。要在里面选出 (5) 个点,(3) 个构成三角形三个顶点,(2) 个构成线段。要求线段和三角形严格不交,问有几种选法。

    day3

    【A,E,I】

      简单题。

    【H】

      待补。

    【F,J】

      不补了。

    【B√】

      题意:给出一个 (N(leq 20)) 个点的确定性自动机,边上是小写字母。从 (1) 号点出发,每次随机找一条出边走过去,并把沿途的字母连接成字符串 (S)。再给出两个字符串 ((A,B) (|A| leq 10,|B| leq 50)),任意时刻当 (A)(S) 子串或 (B)(S) 子序列时停止游走。问路径的期望长度,无穷大输出 (-1)
      题解:很清晰的高斯消元题。子序列的匹配具有单调性,所以可以按 (B) 串分层进行高斯消元。每层共有 (N(|A|+1)) 个点,依据 (fail) 数组建立方程。注意最好先判一下无穷大的情况,包括:①存在一条路径连向下一层或本层的无穷大。②本层一个封闭的圈,不连向任何已经确定的答案。

    【C√】

      题意:给出平面上的 (N(leq 2000)) 个点,求一个面积最小的三角形。
      题解:先枚举三角形的最低点,将它上方的点极角排序。注意,极角序相邻的点不一定就是答案:枚举了其中一个向量后,另一个点必须是距离离它最小的。对于极角序相邻的两个 ((x,y)),做一条从原点开始与其连线平行的向量 (gamma)。观察到,(x)(gamma) 一侧的距离都优于 (y),而 (y) 在另一侧比较优。所以我们可以按极角序压入一些点,维护一个凸壳表示可能成为答案的点集。随着枚举的向量变化,可能会弹出凸壳顶。

    【D√】

      题意:给出一张 (N(leq 1000)) 个点,(M(leq 100000)) 条边的无向图,保证每一个点度数都一样且是偶数。现在要删掉若干边,使得剩下的图里每个点的度数都是 (2)
      题解:考虑网络流模型:左右两排都是 (N) 个点,与起点终点的限制流量都是 (1);原图的一条边 ((u,v)) 在正反连两次。如果满流,每个点都有一个唯一的出点,我们可以根据这个连出若干个环,问题也就解决了。
      实际上还有一个小问题:这样可能会连成二元环,而二元环是不被允许的。所以我们希望原图的每条边只在网络流里被连一次,即给边定向,使得有解性不变。有一种很优美的定向方法:在原图中做一遍欧拉回路,每条边被经过的方向即为它的方向。
      现在我们来证明,这种做法必然能找到解。欧拉回路完后,每个点正好有 (k) 条出边和 (k) 条入边。在网络流的二分图里,考虑左侧的一个集合 (X),它们的出度和是 (k|X|)。因为右侧每个点入度也是 (k),所以与 (X) 关联的右侧点至少有 (k) 个。由霍尔定理,这个二分图存在完备匹配。

    【G√】

      题意:将俄罗斯方块(包含所有旋转型)填入 (4 imes N) 的格子中。求能填满格子的方案数。(N leq 10^9)
      题解:注意俄罗斯方块及其旋转型 其实就是所有四连通的网格。
      一列一列填过去,最多只和前三列有关。可以状压前 (4 imes 3) 的格子信息进行 dp。
      有一种策略是直接暴力 (dp) 1000 项,得到的数列必然是线性递推数列,找寻一下规律即可。
      也可以对上限是 (2^{12}) 种状态进行压缩(因为很多状态可能永远也填不满了)。比赛时直接加了些无脑剪枝,比如 "任意一个白点到右侧那一列的最短路不能超过 (4)",“假设第三列的白色方块数量是 (k),则左三列白色方块不能超过 (3k)”,"如果存在一个 (1 imes 4) 的白条,先假设填上,若之后的状态不行则它也不行"。这样状态只有 (360) 种左右了。再应用对称性可以缩到 (180) 种,预处理转移直接矩乘。

    【K√】

      题意:(2N) 个点排成一个环。要将每两人匹配成一个组,使得在环上有边的组正好有 (K) 组。(1 imes K imes N leq 10000)
      题解:

    day4

    【A,E,I,J,K】

      简单题 / 码农题。

    【B】

      题意:求无穷级数 (sum frac{ln n}{n^s}) 的值。和标准值的绝对误差不能超过 (1e-6)(1.0001 leq s leq 20) , (s) 四位小数。
      题解:待补。

    【C√】

      题意:给出一个字符串 (S(|S| leq 10^5))。有 (Q(leq 3 imes 10^5)) 个询问,每次给出 ((l,r)),问 (l sim r) 之间有多少本质不同的子串。
      题解:如果用 (manacher) 求出每个位置的回文半径 (p_i),那么对于一个询问 ((l,r)),答案就是 (sum_{i=l}^r min(p_i,i-l+1,r-i+1))。比赛时我想的是,每次枚举一个位置 (i),去维护它对所有询问 ((l,r)) 的贡献。(min) 里面有 (3) 个量不太好直接维护。假设我们维护好了((l,r)) 的答案,如果边界变动一格,我们可以用主席树在 (O(log N)) 的时间内求出增量(比如 (l) 减一,就是询问 (sum_{i=l}^{(l+r)/2} [p_i<l])。那么我们可以分块,先用差分数组在 (O(N sqrt N)) 时间内维护出 (f_{b,r}) ,表示第 (l) 个块的开头到位置 (r) 的答案。每次询问时移动 (l) 求增量,询问复杂度 (O(Q sqrt Nlog N))。但这样是过不了的。发现每次移动的询问是彼此独立的,可以先离线下来(为了防止空间不够,可以每隔几百万离线求一次),用桶排+树状数组快速求出答案,几乎可以把原来的主席树的 (O(log N)) 的常数给拿掉。
      比赛中智商降了好多……反过来考虑,固定一个 ((l,r)),求所有 (p) 对它的贡献。 根据 (mid) 划成两半,三维 (min) 就直接变成了二维 (min)……然后离线+线段树或者直接主席树就在 ((N log N)) 时间内轻松解决了……

    【D】

      题意:给出平面直角坐标系里的三个整点表示一个三角形。现在要将其划成若干个小三角形,使得每个小三角形都和原图形相似,且大小两两不同。
      题解:只有正三角形是无解(但是三个整点表示不出正三角形)。在大多数情况都可以用以下Case解决:
      

    【F】

      题意:有一个 (N imes M (N,M leq 1000)) 的网格,((x,y)) 是障碍。用大小为 (3)(L) 型骨牌去覆盖剩下的格子,打印一种方案或输出无解。
      题解:待补。

    【G√】

      题意:图上有 (N) 个点,起初没有边。有 (M) 个操作,每次加入一条边 ((u,v)) 或者删除一条边。每次操作完后询问桥的个数。
      题解:经典的动态桥边计数问题, claris的题解 。设 (solve(l,r,n,m)) 为考虑时间在 ([l,r]) 的修改操作,作用范围是 (n) 个点,(m) 条边的图。设 (E) 表示 ([l,r]) 涉及到的边集,(V) 表示它们两端涉及到的点集。先将 (M-E) 跑一遍 (tarjan),将边双缩点(边双内部的边永远不会是桥)。在剩下的树(森林)中,做出 (V) 的虚树。不在虚树上的边永远都是桥,直接加入答案即可。将剩下的虚树做一张新图,递归左右两个子问题(有个细节是,虚树上的一条边要额外记录对应了原图的几条边,一旦它成为答案,这些边都是桥)。容易发现,每一层做完后,新图的点数和边数都是 (O(r-l))。不计并查集复杂度,总复杂度为 (M log M)
      还有一种 (M log M log N) 的 LCT 做法。将边插入时间线段树,现在只剩下加边了。用 LCT 维护当前森林,如果进来一条边 ((u,v)) 所在的连通块已经连通,就在 (u sim v) 的路径上区间加 (1)。显然,桥的个数即为权值为 (0) 的边的条数,这个可通过在 LCT 的 Splay 上维护子树最小值以及子树最小值个数来实现。注意,每次加入一条边后,只需考虑答案的增量,所以只有链上询问最小值个数,不需要带虚儿子和的 LCT。时间线段树里的回退也能很方便地实现。

    【H√】

      题意:有一棵 (N(leq 10^5)) 个点的树,每条边有边权 ((b_i,c_i)(leq 10^9))。对于一条边 (i),定义 (d_i) 为:考虑根到它的其它所有 (b_j<b_i) 的边 (j)。如果不存在这样的 (j),则 (d_i=c_i);否则 (d_i=median(d_j)+1)(median) 表示符合要求的边的 (d_j) 的中位数。
      题解:在树上DFS。套一个树状数组来满足 (b_i) 这一维的限制,每个 bit 对应一棵动态开点的权值线段树(用来维护 (d_i))。查询时,在符合要求的 (log) 个权值线段树里一起走。时间和空间复杂度都是 (O(N log^2 N))

    【I√】

      题意:给出 (N(leq 1111)) 个不经过原点的平面。从原点开始选择一条射线射出去,问最多能射到多少平面。
      题解:转化的问题是:给出 (N) 个三维向量。求一个向量 ((x,y,z)),使得与它们分别点积后 大于 (0) 的情况数最多。
      我们考虑以这个向量为法向量的平面。由调整法,存在一个最优解,使得这个平面过某个给定的向量。那么我们 (O(N)) 枚举每一个向量,以这个向量为一条边,旋转一周,去寻找最优秀的平面。这时可以转化为,在二维坐标里旋转一周,找一侧点最多的直线。极角排序即可,复杂度 (O(N^2 log N))

  • 相关阅读:
    django 项目需要注意的一些点
    VUE之路
    Oracle 表格碎片的查看方法
    RHEL 6.x or 7.x 使用分区绑定ASM 磁盘的方法
    RMAN 修复主库 nologging 操作导致物理备库的坏块
    Oracle 数据库19c 回退降级到 11.2.0.4 方案
    如何评估oracle 数据库rman全备和增量备份大小
    在将Oracle GI和DB升级到19c或降级到以前的版本之前需要应用的补丁 (Doc ID 2668071.1)
    Oracle 数据库坏块处理
    opatch auto 安装11.2.0.4.20190115 PSU遇到 OUI-67133: Execution of PRE script failed,with returen value 1 报错
  • 原文地址:https://www.cnblogs.com/jiangshibiao/p/10426489.html
Copyright © 2011-2022 走看看