杂题

洛谷博客已隐藏,没有投洛谷题解的题解。

by 0htoAi

LOJ#3188 无人驾驶出租车

可以用线段树维护每行每列的最后一次操作的时刻。对于一个询问,容易得到哪些行列是可以走的。

就三种情况,要不然一横一竖各过一个点。答案为理论最小。要不然两横过两个点,通过一竖传递,要不然两竖过两个点,通过一横传递,对于传递的横竖,一定为左边(上边)最近的或右边(下边)最近的,答案取较小值。最近指离两点中的一点最近。要不然整个中间被填满了,要不然中间所有的行都可以走,要不然所有的列都可以走。这个时候答案也为理论最小。如果三种情况都不存在,就无解。

洛谷P6881 火事

每个值会在后面的一些连续段产生连续且固定的贡献。具体来说,每个点的父亲为前面最近一个比其大的点,对父亲产生的贡献区间为这个点为左端点的极大区间满足这个点为最大值。贡献值为父亲的权值减去自己的权值。

这样就能得到一堆四元组 \((t,d,l,r)\) 表示从 \(t\) 时刻开始,起点在 \(l\) 终点在 \(r\),每个时刻在那个位置加上 \(d\)

可以拆成差分形式 \((t,d,l)\)\((t,-d,r+1)\)

考虑暴力,把询问拆成前缀和形式,询问 \([l,r]\) 拆成询问 \([1,l-1]\)\([1,r]\)。枚举每个询问,枚举每个三元组,如果询问的时间 \(\geq\) 三元组开始产生贡献的时间,就可以列出一个式子算贡献。设询问为 \((op,t_1,r)\)\(r\) 表示前缀和要求的位置,\(op\) 表示 \(1\)\(-1\)。三元组为 \((t_2,d,l)\)\(l\) 表示起点位置。

则当前贡献为:

\[op\times d\times (\min(r,l+t_1-t_2)-\min(r,l-1)) \]

后面一坨表示产生贡献的长度,\(l+t_1-t_2\) 表示能产生贡献的最远地点,\(r\) 为询问限制。而如果 \(r<l\),也可以通过后面的 \(\min\) 抵消掉。

把式子化简得:

\[op\times d\times (t_1+\min(r-t_1,l-t_2)-\min(r,l-1)) \]

发现 \(\min\) 里左右不互相干扰,所以单独用线段树维护每个询问取左边的 \(\min\)\(r-t_1\) 时的 \(sumd\),其它的同理。

上文有个限制,要求 \(t_1\geq t_2\),所以按时间扫描线即可。

洛谷P6054 开门大吉

最小割,每个人开 \(M+1\) 个点,对于中间的 \(M\) 条边,边 \((i,j)\to(i,j+1)\) 的容量为第 \(i\) 个人做第 \(j\) 套题的奖励。割掉表示做。对于限制,即如果一个人割了一条边,则另外一个人必须割多远多远以后的边。所以对于所有 \(j\) 连边 \((x,j)\to (y,j+k)\),容量为 \(\inf\)。表示选了 \(x\) 做第 \(j\) 套题就必须让 \(y\)\(\geq j+k\) 的题。

可能无解,无解的时候无法更新,所以连反边容量为 \(\inf\) 到源点,这样至少能走通。然后如果最大流 \(\geq \inf\) 就无解。

洛谷P5103 断层

倒着操作。发现 \(x\) 坐标的相对大小不变。所以可以用数据结构维护相对顺序下的 \(x\)\(y\)。发现一个操作会让一段前缀加上 \((-L,-L)\),或让一堆后缀加上 \((L,-L)\)。所以可以维护差分。然后简单一点的做法是树状数组维护差分,每次二分找到断点。更快的做法是树状数组上二分找到断点。断点考虑直线的性质,即 \(x+y\)\(x-y\) 为定值。对于一个点,很容易判断是否在要移动的那一面。

LOJ#2740 最差记者2

从排名高的开始,找到 \(\geq B_i\) 的最小的国籍相同的点(双指针时用栈维护,因为不能重复用这个点,用了需要从栈里删掉),然后把这个点用掉。否则就找到 \(\geq B_i\) 的最小的点用掉。在并查集路径压缩的时候,第一种哪怕用的点被第二种先用过,也可以看做没用过而把前面的一个空位当做用过,所以是可行的。

对于第二种情况,答案一定会增加。对于第一种情况,如果用不掉这个点,即这个点左边(包括自己)都满了,就转到第二种情况,答案也会增加。如果能用掉就不增加了。

因为一定有解,所以一直用第二种情况是一定能找到空位的。

其实这是一个很厉害的小 trick,ABC137D,NOI2017蔬菜,eJOI2021Waterfront 都用到了这个 trick。复杂度是线性的


[CCO2023 day1] Binaria

暂无链接。

考虑到 \(i\)\(i+K\) 要不然固定一个 \(0\) 一个 \(1\),要不然就相同为 \(0\)\(1\),在于 \(B\) 的大小。用并查集维护相同的那些。然后考虑初始状态,需要几个问号变成 \(1\),然后就是个组合数。最后答案就是这个组合数。

洛谷P6261 Traffic Blights

今天做题数量少,就是被这道毒瘤耽搁了 \(4\) 个多小时。因为我概率、数论这块都学得很差。

\(m_i=r_i+g_i\)。肯定有个大周期为 \(\text{lcm}_{i=1}^{n}(m_i)\)

只需要在这个大周期里算概率,就是最终概率。

根据中国剩余定理,可得概率为 \(\prod_{i=1}^{n}\frac{g_i}{m_i}\),就是 \(\text{lcm}\) 那一套是互不影响的,因为分母的 \(\gcd\) 都为 \(1\)

考虑用一种奇特的方式消除非互质的贡献。考虑把大周期分成很多块,每块大小为 \(M\),枚举每块的位置 \(b\),然后对于这个位置,算 \(n\) 个红绿灯的周期:在 \(kM+b,k\geq0\) 中的关于 \(k\) 的周期长度,也就是 \(\frac{m_i}{\gcd(M,m_i)}\)。然后通过巧妙地设置 \(M\) 使得这个值要不然为 \(1\) 要不然为质数,然后对于这个值相同的 \(i\),用同一套方法,枚举 \(k\) 的取值算绿灯概率:即要从前面的继承不合法的 \(k\) 的取值,即在取这个 \(k\) 的时候,前面的相同周期的就已经是红灯了。

但是发现最小的 \(M=2^6\times3^4\times5^2\times7^2\)。过不去。考虑把一些小质数周期换成大一点的合数,然后一起讨论,多枚举几个周期。比如把周期为 \(2\) 的看做周期为 \(8\),然后枚举 \(k\)\(8\),贡献也贡献到周期为 \(8\) 的一类数字。但是需要满足,看作的这些合数周期,也需要满足跟其它的质数和合数周期的 \(\gcd\)\(1\)

所以设 \(M=2^3\times3^2\times5\times7\)。然后把所有周期为 \(2\)\(4\) 的改成 \(8\),把周期为 \(3\) 的改成 \(9\)。然后周期就是 \(1、8、9\) 和除了 \(2\)\(3\) 之外的质数,也满足互质的条件。

所以也可以通过把所有不同周期的碰到绿灯的概率乘起来。算个前缀和,每个灯都要单独算概率。相同周期也要单独算概率乘起来,但共用一套找绿灯在哪些位置出现的方法。

因为在枚举 \(b\),所以最后的 \(ans_i\) 要乘一个 \(\frac{1}{M}\)。答案\(ans_i\) 表示走到 \(i\) 号灯还是绿色的概率,最后输出的是差分数组。

洛谷P6010 Falling Portals P

考虑 \(a_i\geq a_{q_i}\) 的情况,从起点出发,每次能瞬移且瞬移后下降得更快,肯定下降。反之同理。

所以考虑把每个奶牛的下降轨迹画一个 \(y-t\) 图,表示当时间为 \(t\) 时这头奶牛的 \(y\) 坐标在哪里,横坐标为 \(t\),纵坐标为 \(y\)。然后发现一个奶牛 \(a_i\geq a_{q_i}\) 的最优方案一定是在 \((0,a_i)\) 为起点走一段凸包再径直走向 \(q_i\) 那条直线直到相交。发现是有单调性的,所以可以在凸包上二分求出是从哪里走到 \(q_i\) 那条直线。\(a_i \leq a_{q_i}\) 的同理,只是凸包的方向变了。

用单调栈维护凸包然后二分即可。

CF1830C Hyperregular Bracket Strings

首先每个限制能够直接确定两个坐标是什么括号。把所有已经确定的位置看做一个括号串,一对匹配括号的贡献为这对括号在原本串围起来的区间里面没有被确定的括号所组成的合法括号串数量。然后把这一整个区间都删掉,不对更外围的括号对产生贡献。

一个结论是,一个长度为 \(x\) 的括号串的方案数为卡特兰数的第 \(\frac{x}{2}\) 项。如果 \(x\) 为奇数就是 \(0\)

所以就把一堆卡特兰数乘起来就行。

CF1830E Bully Sort

考虑操作次数为 \(c\) 次,操作序列为 \(x,y\),第 \(i\) 次交换 \(p_{x_i},p_{y_i}\)

一次操作逆序对数量会减少 \(2(x_i-y_i)-1\) 次。则初始逆序对数量 \(c1=-c+2\sum_{i=1}^{c}(x_i-y_i)\)

则:\(c=2\sum_{i=1}^{c}(x_i-y_i) -c1\)

注意到\(\sum_{i=1}^{c}(x_i-y_i)=\sum_{i=1}^{c}\max(p_i-i,0)\)。考虑证明只需要把每次交换后此式的 \(\Delta\) 写出来,然后对于每个 \(\max\) 分别讨论,最后发现一次操作的 \(\Delta_i=(x_i-y_i)\)

所以只需要动态维护逆序对数量和 \(\sum_{i=1}^{c}\max(p_i-i,0)\) 即可求出 \(c\)

洛谷P6406 Norma

考虑分治。对于过当前中点的区间,考虑枚举区间左端点,随着右端点从左往右移动,区间 \(\min\)\(\max\) 会越来越右。预处理 \([Mid+1,i](r \geq i \geq Mid+1)\) 区间的 \(\max\)\(\min\)。枚举左端点的时候也维护一下左边当前区间的 \(\max\)\(\min\)。每次可以把右边的区间分成至多三块,左边一块用的最值的下标全是 \(\leq Mid\) 的,中间的块就是一个最值在左边,一个最值在右边的,右边的块就是最值全在右边的。块可以双指针维护。预处理前缀和快速算每一块的答案。

CF1787I Treasure Hunt

一个区间的美观度为最大前缀和(至少为 \(0\))加最大子段和(至少为 \(0\))。

所有区间的最大前缀和之和可以用单调栈求。预处理前缀和,从后往前枚举区间左端点,维护后缀和表示一个后缀每个点为当前右端点的前缀和最大值之和。也可以用同样一个单调栈快速更新后缀和。每次在单调栈上二分找到最近的比 \(Sum_{i-1}\) 大的位置。其后方为右端点的区间都是合法的。

每个区间的最大子段和考虑分治。对于穿过中点的区间,最大子段和的区间可以分为全在左边,穿过中点,全在右边。预处理左边区间的后缀最大值和后缀最大子段和,右边区间的前缀最大值,前缀最大子段和。发现如果右边区间的前缀最大值更新,则前缀最大子段和一定会更新
。然后又可以枚举左边为左端点,右边分成三段,一段的最大子段和为左边的最大子段和,一段的最大子段和为左边的前缀最大值加右边的前缀最大值,一段的最大子段和为右边的最大子段和。然后就像上一道题一样做。

LOJ#2773 学习轨迹

看做平面直角坐标系,值代表长度。答案至少为一方全取,另一方全不取,所以如果两方取得的值均没有超过自己总和的一半一定是亏的。所以一定有一方取得的值之和会超过其总和的一半。所以排序后找到刚好在一半位置处的点。

把一对相同编号的课程看作一个长方形障碍。求的答案是最大的不与障碍有交集的长方形的长加宽。

把第一个学校看作横坐标,第二个学校看作纵坐标,枚举纵坐标的顶端,用线段树维护每一个可能的纵坐标底端所对应的横坐标的左和右延伸的距离。用 \(2\) 个单调栈来维护中线左边和右边的阻挡。

顶端已经枚举固定了,所以从上往下宽度单调变窄。单调栈弹出一个值的时候把线段树对应区间也改一下即可。

UOJ#805 设计草图

把问号全填左括号后满足所有前缀左括号数量大于等于右括号数量的极大区间和问号全填右括号后满足所有后缀右括号数量大于等于左括号数量的极大区间求出来。然后二维偏序一下即可:分奇偶讨论,枚举所有第一类区间,找到有多少个右端点在这个区间,左端点在这个区间左边的第二类区间有多少个,它们的交集就一定是合法的括号串。

LOJ#524 游戏

最后一个放的人能够使逆序对为任意奇偶性。所以最后一个操作的人是谁谁就赢。特殊情况是 \(n=1\) 或没有操作,没有操作需要求逆序对数量。

AGC009E Eternal Average

分解成 \(\sum k^{-x_i}\) 这样的形式。看成一个 \(k\) 进制小数。

\(\sum_{i=1}^{n+m} k^{-x_i}=1\),即假设所有数都是 \(1\),最后答案为 \(1\)。求的是 \(\sum_{a_i=1} k^{-x_i}\) 的取值个数。考虑到进位的关系,\(\sum_{a_i=1} x_i \equiv m \mod k−1\)\(\sum_{a_i=1} x_i \leq m\)。对于 \(a_i=0\) 的数也同样的道理。且可以通过枚举当前的小数位数和 \(\sum_{a_i=1} x_i\) 来倒推 \(\sum_{a_i=0} x_i\)

所以枚举小数位数和 \(\sum_{a_i=1} x_i\) 的值 dp 转移即可。dp 还需要加一维表示当前小数最后一位是否为 \(0\),统计长度为当前枚举的长度的答案时不统计最后一位为 \(0\) 的小数。

CF1264E Beautiful League

完全图一定不亏。考虑一个三元组是三元环,当且仅当每个点都贡献一个出度,而不是三元环,当且仅当有一个点贡献两个出度,另外一个点贡献一个出度,最后一个点没有出度。希望让三元环尽量多,就要让三元组存在贡献两个出度的点的尽量少。一个点的出度为 \(d_u\),则有 \(d_u\) 为那个贡献两个出度的点的三元组数量为 \(\binom{d_u}{2}\),因为固定两条边就能固定一个三元环。

所以答案为 \(\binom{n}{3}-\sum_{u=1}^{n}\binom{d_u}{2}\)。展开发现是一个与 \(-{d_u}^2\) 有关的式子,因为要让值尽量大,所以要让 \({d_u}^2\) 尽量小。考虑费用流定向,把每条边拆成一个点,流入一个水,向其连接的点连边(如果这条边已经被定向就只连起点边)。然后每个点向汇点连 \(n-1\) 条边,第 \(i\) 条边代表当前出度已经为 \(i\),则第 \(i\) 条边的费用为 \(i^2-(i-1)^2\)

AGC035E Develop

只会操作最后被擦掉的数。操作最后还在黑板上的数一定不优。

\(k\) 为偶数,分奇偶算方案数然后乘起来。对于一种奇偶性,只要存在连续一串长度为 \(\frac{k}{2}+1\) 的数就无解:成环。随便 dp 一下就好了。

\(k\) 为奇数,考虑建图,然后考虑对齐奇偶,把奇数 \(i\) 与偶数 \(i+k\) 对应,把图分为两列,但统一层的标号,奇数的层为 \([\frac{k+1}{2},\lfloor \frac{n+k}{2} \rfloor]\),偶数的层为 \([1,\lfloor \frac{n}{2} \rfloor]\)

发现如果一个方案不存在当且仅当这个方案里面被操作的点在这个图上成环。这个图每个简单环大小都为 \(k+2\),其中那个 \(2\) 为一条从奇数到偶数的 \(+k\) 边和偶数到奇数的 \(-k\) 边。

考虑 dp 状态 \(f_{i,j,k}\) 表示前 \(i\) 层,当前层的奇数点的往上走连续点的数量(的最大值)为 \(j\),当前层为偶数点的连续点的数量为 \(k\) 的方案数。向上走指不考虑偶数到奇数的连边。偶数只会一直向上走,而奇数可能会在某处拐到偶数:当且仅当那奇偶都能取到。

奇数连续长度 \(\geq k+2\) 时一定存在环,否则一定不存在。考虑那条从偶数到奇数的边即可。所以枚举每层奇偶数字取的情况然后 dp 转移即可。如果同时选,则奇数最大连续段长度为 \(\max(j+1,k+2)\),即右边拐过来,增加两个点。最后答案为 \(\sum_{i=0}^{k+1}\sum_{j=0}^{\lfloor \frac{n}{2} \rfloor} f_{\lfloor \frac{n+k}{2} \rfloor,i,j}\)

CF1017G The Tree

极其多做法。我的做法是初值全为 \(-1\),对于染黑操作,单点加,对于染白操作,全子树减,且在子树根节点的位置(即输入的那个点)添加一个阻塞量使得上面的贡献的下不来。查询就是找这个点到根的路径上的最大后缀和是否 \(\geq 0\)。会发现这样做其实就是模拟,很人类智慧。


LOJ#2351 毒蛇越狱

对于一个查询,\(\min(cnt_0,cnt_1,cnt_?)\leq6\)。然后对于这三种情况,都可以枚举这个种类的子集跑容斥(问号甚至不需要容斥)。时间复杂度 \(O(2^{L}L+2^{\frac{L}{3}}Q)\)。有另外一种根号分治的做法,可惜我不会。

LOJ#2743 摩天大楼

从小到大把值加入。忽略掉绝对值。如果最后的答案存在一个 \(A_i-A_j(i>j)\),则可以看成存在一个 \(\sum_{k=j+1}^{i}A_k-A_{k-1}\)。所以加入一个值产生的贡献就是能够找到多少个已填连续段贴着,一个连续段的左和右都能贴(除了边界),所以产生的贡献为当前连续段数量 \(\times 2-t\),其中 \(t\) 表示有多少个连续段把边界占领了(\(t\leq2\))。

可以列出 dp 状态 \(f_{i,j,k,t}\) 表示前 \(i\) 个值,\(j\) 个连续段,算式的值为 \(k\),有 \(t\) 个连续段把边界占领的方案数。然后枚举每一个填的数会对当前局面产生的影响,不过无论怎么填,下一个状态的 \(k\) 都会是这个状态的 \(k+(A_i-A_{i-1})\times(2j-t)\)

填的方式有:不贴段,贴一个段,贴两个段(合并到一起)。其中前两个方式还要讨论是否是边界(当 \(t\leq1\))。

答案为 \(\sum_{i=0}^{L}f_{n,1,i,2}\)。时间复杂度为 \(O(n^2L)\)

LOJ#2833 帐篷

dp。\(f_{i,j}\) 表示 \(n=i,m=j\) 时的答案。考虑去掉最后一行,如果这一行什么也不选,得到 \(f_{i-1,j}\)。如果选一个位置,任意定向,则那一行那一列都不能要了,得到 \(4j\times f_{i-1,j-1}\)。如果这一行选两个互相对着的点,那这两列也不能要了,得到 \(\binom{j}{2}\times f_{i-1,j-2}\)。如果这一列选一个点再在其它行选一个点,那么那一行也不能要,得到 \(j(i-1)\times f_{i-2,j-1}\)

LOJ#2836 最差记者 3

算出每个人往前走的周期:每隔多久走多长。可以递推来算。然后每次询问拆成两个前缀询问,对于每个询问二分答案即可。

LOJ#2840 糖

典得要命的贪心。链表+堆。

LOJ#2842 野猪

任意两点间维护 \(4\) 条最短路,前两条保证起始边和终点边各不相同,后两条的起始边和终点边各与前两条的一条不相同。即:\((x1,y1),(x2\neq x1,y2 \neq y1),(x3\neq x1,y3\neq y2),(x4\neq x2,y4\neq y1)\)。可以归纳得到不走回头路的最短路径一定可以通过这些路径合并得到。

合并的方法就是分四次枚举左右各选哪条路,然后判断一下就行。

然后就可以用线段树维护修改了。

最短路要用边到边之间的最短路,线段树每个节点代表一个间隔。

posted @ 2023-08-09 08:45  0htoAi  阅读(68)  评论(1编辑  收藏  举报