序列

题目

解法

首先你会发现题目中神神叨叨的操作并没有什么渜用,实际上一个序列合法当且仅当权值和 \(\ge\) $k\times $ 序列长度。

\(a\) 求前缀和 \(pre_i\),这也等价于 \(pre_r-rk-(pre_l-lk)\ge 0\) 时答案可为 \(r-l\)。二分序列长度可以做到 \(\mathcal O(nm\log n)\),过不去。

考虑对于特定的 \(r\),我们希望 \(pre_l-lk\) 尽量小,但这同时意味着 \(l\) 会更大。所以用双指针维护:从大到小枚举 \(r\),对于每个 \(r\) 维护最小的满足条件的 \(l\)。需要注意的是,\(r\) 的减小可能会导致 \(l\) 不再合法,但由于题目只要求最大的 \(r-l\),如果 \(l\) 再增大肯定不优,所以我们 “按兵不动,静候良机”。

\(\text{CodeForces - 407E k-d-sequence}\)

题目

传送门

解法

懒了,直接贴学长的 \(\rm orz\)

\(\text{Minimal Power of Prime}\)

预处理 \(n^{\frac{1}{5}}\) 之内的质数,剩下的质数都 \(>n^\frac{1}{5}\),所以不会超过 \(4\) 个。

除了 \(n=a^4,a^3,a^2\),其它的最小值就都是 \(1\) 了。注意要先判断 \(a^4\),因为它会被 \(a^2\) 误判。

\(\text{P1852 }\)跳跳棋

\(2\) 年前竟然做过这题... 完全没有印象。

考虑每种状态往里走的方式是固定的,当相邻棋子距离相同时无法移动。

这很像一棵树!所有状态就是一个森林。

设当前态为 \(s\),目标态为 \(t\)。首先判断它们是否在同一棵树。然后将它们挪到同样的深度,二分它们与 \(\rm lca\) 的距离即可。

考虑怎么加速 “跳” 这一 \(\mathcal O(d)\) 的过程。考虑每次转向(方向即为最右棋子/最左棋子下标不变)区间长度至少减掉 \(\frac{1}{3}\),所以转向复杂度可以承受,每个方向行走的距离推一推就行了。

还有一个单 \(\log\) 的做法:传送门

\(\text{CodeForces - 1027D Mouse Hunt}\)

每个点都是有出度的,这也就意味着每个点最后都会走到环上。

贪心地想,我们在环上选最小值一定比在链上选更优。因为在链上选时,环上的点仍然无法到达,还会选择环上的最小值。注意,由于每个点只有一个出度,不会有环连着环这种难以判断的情况。

感觉这个博主的实现很精细。其中 \(\text{mark[]}\) 是因为一个连通块只有一个环,我们将环的值选了之后这个连通块都合法了,所以要整体标记,把没遍历的点也标记。

\(\text{CodeForces - 985F Isomorphic Strings}\)

我们将每个字母的出现位置进行哈希,查询时判断 \(26\) 个字母得出的哈希在数字上是否全等即可。

\(\text{[HAOI 2008] }\)硬币购物

首先做一个完全背包。考虑硬币数目非常小,我们可以枚举每种硬币 \(i\) 是否满足条件 \(p_i\) 然后进行大力容斥。

具体就是满足 \(p_i\) 是硬币 \(i\) 购买个数超过 \(d_i\)。这样我们可以 钦定 满足 \(p_i\) —— 即 \(dp_{s-(d_i+1)\cdot c_i}\)。类似地,还可以 钦定 同时满足 \(p_i\)\(p_j\) —— 即 \(dp_{s-(d_i+1)\cdot c_i-(d_j+1)\cdot c_j}\)

\(\text{Cutting Plants}\)

维护一个单调不增的双端队列,元素 \(i\) 表示将第 \(i\) 株植物砍成 \(b_i\) 的操作。

  • b[q.back()]<b[i]。队尾的操作不能操作在第 \(i\) 株上,所以后面也不行。
  • b[q.front()]>a[i]。队头的操作不能操作在第 \(i\) 株上,所以后面也不行。

\(\text{A Magic Lamp}\)

先开始的思路是令 \(l=1,r=n\),用 \(\rm st\) 表找出最左边的最小值下标 \(pos\),如果删不了就将右边界缩小。但实际上这面临着一个问题:缩小之后由于前面不会删除一些下标,我们又可以选择这个最小值。

更好的方法是先令 \(l=1,r=m+1\),这样保证不出现删不了的情况。接着转移到 \(l=pos+1,r=r+1\) 即可。

\(\text{Heapsort}\)

先正向考虑,如何才能最大化次数?第一次操作,必将把堆顶的 \(n\) 与堆底 \(1\) 交换。此时我们最好让 \(1\) 顺次向下交换,交换到 \(n-1\) 的位置,这样还能保证下一次操作 \(1\) 又到了堆顶。剩余的依此类推…

倒着模拟,先把 \(1\) 放在堆顶(这相当于 \(2-1\)),接着将 \(1\) 经过路径的数向下移动。最后处理堆顶和当前堆底元素就完成了一次倒退。

\(\text{Dist Max 2}\)

首先考虑到二分 \(k\)。那么我们就需要找到一组 \(i,j\) 满足 \(|x_i-x_j|\ge k\)\(|y_i-y_j|\ge k\)

可以考虑用一个特殊的队列维护:将 \(x\) 从小到大排序,插入 \(i\) 时,满足第一个条件的 \(j\) 被踢出队列,将 \(j\)\(y\) 值取 \(\max,\min\)

\(\text{CF1354E Graph Coloring}\)

\(dp_{i,j}\) 为前 \(i\) 个二分图,选了 \(j\)2 是否可行。这是 \(\mathcal O(n^2)\) 的。

考虑如何计算答案。由于每个二分图都一定选了一部,所以从 \(dp_{cnt,tot_2}\) 开始逆推,每次查询 \(dp_{i-1,cur-b_{i,0}},dp_{i-1,cur-b_{i,1}}\) 即可。

\(\text{[BJOI 2016] IP}\)地址

我们将 \(\mathtt{ip}\) 拿来建一棵 \(\rm trie\) 树。考虑树上两个节点 \(i,j\),其中 \(i\)\(j\) 的父亲。那么如果 \(j\) 节点有 \(\mathtt{ip}\),被影响的节点只有终点为 \(i\)\(fa_j\) 的询问。

类似线段树,添加 add 标记。当 \(i\) 做出更改时 \(add_i\) 加一,在修改和询问的过程中往下传,知道节点有 \(\mathtt{ip}\) 的地方为止。

\(\text{abc187E Through Path}\)

巧妙的树上差分。对于修改 \(u\) 的子树的操作,可以直接在 \(c_u\)\(k\);反之,可以转化为在 \(c_u\)\(k\),整体再加 \(k\)。最后一次 \(\rm dfs\) 即可。

\(\text{CF1148E Earth Wind and Fire}\)

首先可以将两个数列排序,\(s_i\) 最终要到达 \(t_i\)。考虑当两个石头的路径发生交叉时,它们本身可以交换。所以正确性保证。

\(\delta_i=t_i-s_i\),由于只有 \(s_i\le s_j\) 时,\(i,j\) 才可以向里逼近,所以要求 \(\forall i,\sum_{j=1}^i \delta_j\ge 0\)。具体可以用括号匹配来理解,\(1\) 相当于左括号,\(-1\) 相当于右括号。

在计算答案时,用一个栈维护大于零的 \(\delta_i\) 即可。每次配对一定会消耗一个数,总共只有 \(n\) 个数,所以种类数是 \(n\) 级别的。

\(\text{CF1326E Bombs}\)

由于答案是递减的,可以使用调整法。一个显著的好处是当 \(\rm check\) 一个值 \(x\) 是否被炸时,我们无需判断比 \(x\) 大的数。

考虑将 \(\ge x\) 的数赋值为 \(1\),炸弹赋值为 \(-1\)。那么 \(x\) 被炸实际上就是对于任意位置都有 \(suf_i\le 0\)\(suf\) 为后缀和)。考虑若存在 \(suf_i>0\),而 \(>x\) 的数字一定先牺牲,所以 \(x\) 就可以空出来。

用线段树动态维护后缀和即可。

\(\text{POJ - 3635 Full Tank?}\)

题目描述

一辆带有一个容量有限的油箱的车子在一张图上行驶,每行驶一单位长度消耗一单位油,图上的每个点都可以加油,不过都有各自的单位费用。
\(Q\) 次询问,每次给出车的油箱的容量 \(c\),起点和终点,问从起点驾驶到终点的最少花费是多少。
\(Q\le 100,c\le 100,n\le 1000,m\le 10000\)

解法

拆点,把原图的一个点 \(i\) 拆成 \(c+1\) 个点 \((i,j)\),表示在 \(i\) 点油量为 \(j\)。按 "加油" 或 "开汽车" 转移。跑最短路即可。

\(\text{usOJ - 9941}\)

题目描述

甲从 \(A\) 走最短路到 \(B\),乙从 \(C\) 走最短路到 \(D\)。每个时间可以走一步,或者等着。如果某个时间甲和乙在相同的点,就可以得一分,不过一个点上只能得一分。
问最多可以得几分。
\(n≤50000,m≤200000\)

解法

先将 \(A\rightarrow B,C\rightarrow D\) 的最短路上的点分别建成两个 \(\rm dag\)。只保留在两个 \(\rm dag\) 中的点和它们的边,求一个最长路。

由于最短路中不可能有环,所以保证正确性。

墨墨的等式

首先可以差分一下,询问 \([0,w]\) 区间内的答案。

\(\delta\)\(a\) 中的某个数,那么如果 \(\sum a_ix_i=r\) 满足,\(\sum a_ix_i=r+k\cdot \delta(k\in \rm N)\) 也满足。如果枚举 \(r\in[0,\delta)\),求出满足 \(\sum a_ix_i\equiv r\pmod \delta\) 的最小值,那么与其同余的在 \([0,w]\) 之间的解就可以 \(\mathcal O(1)\) 地求出。

由于此题 \(n,a_i\) 范围极小,我们可以考虑将其转化为图上问题:令 \(dis_i\) 为余数 \(0\) 到余数 \(i\) 的最短路。边数是 \(n\cdot\delta\) 级别的,所以我们令 \(\delta=\min a_i\) 以减少边数。

最后跑最短路即可。

牛牛种小树

一个结论是:无论给每个点分配多少度数(\(>0\)),只要和为 \(2n-2\) 就一定可以构造出合法的树。

考虑度数大于零的限制,我们先给每个点分配一个度数,这样就还剩 \(n-2\)。于是 \(dp_i\)\(n-2\) 度分配了 \(i\) 度的最大价值。转移时枚举给某个点拔高的度数,这样的点一定是存在的。

时代的眼泪

题目描述

给定一棵树,对于 \(i\in [1,n]\),输出

\[\sum_{j\neq i}\sum_{x\in P(j,i)} [w_x>w_j] \]

其中 \(w_i\) 给定,\(P(i,j)\)\(i,j\) 之间路径的点集。

\(n\le 10^6,w_i\le 10^9\)

解法

这是一个换根 \(\mathtt{dp}\),于是问题转化为求 \(\rm dfs\) 序在某区间的点中权值严格小于 \(v\) 的点个数。

这个可以用主席树维护,但是线段树常数过大。你会发现这个问题不涉及修改,于是可以往离线的方向考虑:从小到大枚举 \(w\),用一个数据结构维护 \(\rm dfs\) 序,那么就天然满足 "权值严格小于" 的条件。

具体地,用树状数组维护 \(\rm dfs\) 区间内小于当前权值的点个数。我们就可以求出换根 \(\mathtt{dp}\) 的变化量。

posted on 2021-07-16 10:01  Oxide  阅读(60)  评论(0编辑  收藏  举报