abc369 题解
切了 A~F,还挺开心(但是如果上一次把 G 切了的话,我就上青了 QAQ
比赛链接:https://atcoder.jp/contests/abc369
A - 369
题意:
给定正整数 \(a,b\)(\(1\le a,b\le 100\)),请问有多少个整数 \(x\) 满足 \(a,b,x\) 排序后构成等差数列。
思路:
观察到 \(a,b\) 范围很小,直接枚举 \(x\) 即可。
代码:
https://atcoder.jp/contests/abc369/submissions/57274734
B - Piano 3
题意:
给定 2 个序列 \(a,b\),序列长度分别为 \(n,m\),求 \(\sum_{i=2}^n \lvert a_i-a_{i-1}\rvert+\sum_{i=2}^m \lvert b_i-b_{i-1}\rvert\)。
思路:
按题意模拟即可。
C - Count Arithmetic Subarrays
题意:
给定一个长度为 \(n\)(\(1\le n\le 2\times 10^5\))的序列 \(a\),求 \(a\) 有多少个子串 \(b\) 满足 \(b\) 升序排列且为等差数列。
思路:
容易发现一个性质:若 \(a[l\ldots r]\) 为等差数列,且 \(a[l\ldots r+1]\) 不为等差数列,那么 \(a[l+1\ldots r+1]\) 不为等差数列,\(a[l\ldots r+2]\) 也不为等差数列。
那么我们可以双指针,让 \(r\) 从 \(l\) 开始扩展,扩展到 \(a[l\ldots r]\) 为等差数列时,且 \(a[l\ldots r+1]\) 不为等差数列时,计算方案数为 \(\dfrac{(r-l+1)(r-l+2)}{2}\),但是这样计算会把长度为 \(1\) 的子串算重,那么可以将长度为 \(1\) 的子串不在双指针中计算,那么每次计算的方案数为 \(\dfrac{(r-l)(r-l+1)}{2}\),最后再将答案加 \(n\) 即可。
代码:
https://atcoder.jp/contests/abc369/submissions/57289604
D - Bonus EXP
题意:
给定一个长度为 \(n\)(\(1\le n\le 2\times 10^5\))的序列 \(a\),定义 \(\operatorname{f}(b)=\sum_{i=1}^{\lvert b\rvert} b_i\times[(i-1)\bmod 2+1]\)。求 \(a\) 的所有子序列 \(b\),\(\operatorname{f}(b)\) 的最大值。
思路:
选取子序列,可以想到动态规划。设 \(f_{i,0/1}\) 表示选到了第 \(i\) 个数,当前选到新序列中编号模 \(2\) 为 \(0/1\) 所得到的分数的最大值。\(f_{i,0}\) 可以由 \(f_{j,1}(0\le j\lt i)\) 转移过来,但是可以发现 \(f_{i-3,1}\) 一定比 \(f_{i-1,1}\) 更优,因为中间可以在插一个偶数编号。同理,\(f_{i-2,1}\) 也一定比 \(f_{i-4,1}\) 更优,那么 \(f_{i,0}\) 只要从 \(f_{i-1,1}\) 和 \(f_{i-2,1}\) 转移过来即可。
代码:
https://atcoder.jp/contests/abc369/submissions/57296836
E - Sightseeing Tour
题意:
给定一张 \(n\) 个点 \(m\)(\(2\le n\le 400,n-1\le m\le 2\times 10^5\))条边的无向带权图,图中可能会有重边,但不会有自环。给定 \(T\) 次询问,每次询问给出 \(k\)(\(1\le T\le 3000,1\le k\le 5\))条图上的边,求从 \(1\) 到 \(n\) 经过这 \(k\) 条边的最短路。
思路:
经过这 \(k\) 条边相当于每次从到达的点开始往还没经过的边的任意一个端点走,然后再走该边,这样题目就化成选边的顺序了,又观察到 \(1\le k\le 5\),考虑状压 dp。
设 \(f_{i,S}\) 为到达第 \(i\) 个点,已经过给定边集的子集 \(S\) 的最短路径(这里的 \(i\) 数量很有限,只可能是给定边的端点)。
枚举集合 \(S\),再枚举集合 \(S\) 中的元素 \(i\),设集合 \(T\) 为集合 \(S\) 中除去元素 \(i\) 的集合,再枚举集合 \(T\) 中的元素 \(j\)(若集合 \(S\) 中只有 \(1\) 个及以下的元素,那么会被预处理算出),考虑用 \(f_{u_j/v_j,T}\) 转移得到 \(f_{u_i/v_i,S}\),很显然有 \(f_{u_i,S}\gets f_{u_j,T}+d_{u_j,v_i}+w_i\)(\(d_{u,v}\) 表示图中 \(u\) 到 \(v\) 的最短路径。\(v_i,v_j\) 同理转移)。
考虑初始化,\(f_{u_i/v_i,\varnothing}=d_{1,u_i/v_i},f_{u_i/v_i,\{i\}}=d_{1,u_i/v_i}+w_i\)。
求解 \(d\) 数组可以用 floyd 求解,总时间复杂度应该是:\(O(n^3+T\cdot k^2\cdot 2^k)\)。
代码:
https://atcoder.jp/contests/abc369/submissions/57335439
F - Gather Coins
题意:
现在有一个 \(h\times w\) 的网格,网格上有 \(n\) 枚金币,第 \(i\) 枚金币在网格 \((x_i,y_j)\) 处,现在你在网格 \((1,1)\) 处,你想走到网格 \((h,w)\) 处且获得最多的金币,你每次只能向下或向右走。请问你做多能获得多少金币,并输出其中的一种路径。
思路:
容易发现路径的横纵坐标是单调不减的,所以所获得到的金币的横纵坐标也都得是单调不减的,且若所获得的金币的横纵坐标都是单调不减的,那么你一定都能获取到。那么其实就是要求金币按照横坐标从小到大排序后,选取子序列最长且满足纵坐标单调不减,那么题目就转化成了二维偏序问题,可以用最长不下降子序列解决。