7
https://www.luogu.com.cn/problem/P9521
这题也太宇宙了!
从 \((i,j)\) 走到 \((k,l)\) 有两种方式:
- 先到 \((i,l)\) 再到 \((k,l)\),花费 \(a_i(l-j)+b_l(k-i)\);
- 先到 \((k,j)\) 再到 \((k,l)\),花费 \(a_k(l-j)+b_j(k-i)\)。
移项可得,第一种方式更优等价于 \(\dfrac{b_l-b_j}{l-j}<\dfrac{a_k-a_i}{k-i}\)。把这个式子再写开一项可以发现,对于所有对答案有贡献的 \(a_i\),\((i,a_i)\) 构成一个凸包,\(b\) 也是同理。所以把 \(a,b\) 的凸包都求出来,然后拿两个指针做类似凸包合并的过程,每次选斜率较小的那个走,就可以得到答案了!
https://zhengruioi.com/problem/3334
先把所有行按照 \(sum\) 排序。\(sum\) 相同的行必须构成连续的循环移位串。现在我们需要 check 两组循环移位串之间的两两大小关系。
其实不需要 \(O(n_1n_2m)\) 的两两比较,只需要把第二组中的一个串跟第一组中的所有串比较,第二组中的其他串和第一组中的串的大小关系可以直接查表得到。复杂度 \(O(n_1n_2+n_1m)\),由于 \(n_1,n_2\) 都不超过 \(m\),所以复杂度是很对的。
https://www.luogu.com.cn/problem/P9291
考虑 \(O(n\log n)\) 的做法。从大到小依次让每个数归位,当我们要让 \(i\) 这个数归位时,只要 \(p_i\not=i\) 就一直操作 \([p_i,i]\) 这个区间,这样每次都能让 \(i-p_i\) 减半,总次数就是 \(O(n\log n)\)。需要大约 \(30000\) 次操作,无法通过。
我乱搞的方向是,考虑找到一个最小的 \(j\),使得 \(p_j,p_{j+1},\dots,p_i\) 的奇偶性全都相同,然后一次操作可以让 \([j,i]\) 内的所有数到其位置的距离都减半。这个做法可以让操作次数期望乘 \(\frac{1}{2}\),可以通过。
考虑正经的做法。正着做不好做,不妨逆过来做,把 \(b=\{1,2,\dots,n\}\) 复原成 \(a\)。从大到小枚举 \(i\),尝试让 \(a_i\) 归位。如果 \(2\times p_{a_i}\le i\),就操作 \([1,2\times p_{a_i}]\);否则操作 \([2\times p_{a_i}-i+1,i]\)。
来分析复杂度!我们把 \(x=p_{a_i}\) 看作在 \([1,i]\) 范围的的随机数。把 \(a_i\) 归位的次数是 \(\log_{\frac{i}{x}}\)(之前这个东西是 \(\log(i-x)\)),它的期望是一个常数!于是复杂度 \(O(n)\)。
https://www.luogu.com.cn/problem/P12558
考虑确定了集合 \(S\) 之后要怎么 check。设 \(S\) 的补集为 \(T\),那么肯定是让 \(S\) 跟 \(b\) 里面前 \(k\) 小的去匹配,\(T\) 跟 \(b\) 里面前 \(n-k\) 大的去匹配。枚举 \(k\) 之后做背包,可以得到 \(O(n^3)\) 的做法。
可以感受到枚举 \(k\) 这一维是非常浪费的,考虑优化。如果依照和 \(b_k\) 的大小关系把 \(a\) 分成两段,那么前一段天然地能被放进 \(T\),后一段天然的能被放进 \(S\)。剩余部分的 check 就只跟前后缀有关了,跟 \(k\) 无关了!于是对前后缀分别做个背包,求答案的时候拼起来。时间复杂度 \(O(n^2)\)。
https://www.luogu.com.cn/problem/P13342
建出 Kruskal 重构树,那么询问的就是编号在 \([l,r]\) 内的点构成的虚树的点权和。
考虑每个点什么时候有贡献,直接 dsu,贡献区间只有 \(O(轻子树大小)\) 个。然后二维数点就做完了。
https://www.luogu.com.cn/problem/P13695
这种题到底是什么样的强者在切!
我们钦定边上的标签表示:如果是 \(0\),表示这条边的方向是从编号小的指向编号大的;否则从大的指向小的。现在我们需要给图定向。
先按照到 \(t\) 的距离给图分层,层数大的向层数小的连边。我们需要找到一种层内连边的方式以及游走策略,满足在整个游走过程中,经过的同层边数量不超过 \(\log\)。
考虑从深往浅枚举每一层,依次确定该层内的连边方式。考虑使用类似 dsu 的方式,给每个点设置一个点权 \(s_i\)。当我们想要确定 \((x,y)\) 这条边的方向时,如果 \(s_x<s_y\),就从 \(x\) 指向 \(y\),然后把 \(s_x\) 清零;否则从 \(y\) 指向 \(x\),把 \(s_y\) 清零。如果我们能够保证,在游走的过程中,一个点在同层内只会走向那个把其点权清零的点,那么总共的同层边数量就一定不超过 \(\log\) 了。注意到在游走过程中唯一区分点的方式是点的编号,所以猜测游走策略形如“走向编号最大的点”。这样的话,我们在定向时也需要保证将 \(s_x\) 清零的点是 \(x\) 连向的编号最大的点。只需把同层的边按端点编号从大到小排序,然后依次按照上述方式确定方向即可做到这一点。

浙公网安备 33010602011771号