do_while_true

一言(ヒトコト)

XX Open Cup, Grand Prix of Tokyo

Little Vegetable Chickens in Shandong 二队: donghanwen, do_while_true

Accepted:E(dwt)F(donghanwen)H(donghanwen)

H

\(t=10^9\),构造出四个点分别为 \((-t+1,0),(0,t)\)\((0,-t),(t,1)\)

E

ARC156D 的 dp,用 bitset 优化就行。

F

根据排序不等式,答案的下界应当为 \(\sum |a_i-b_i|\),那就尝试构造出这个下界。尝试归纳然后反证,就 \(b_1\) 不能引爆 \(a_1\) 那么 \(b_1\) 距离 \(a_2\) 比距离 \(a_1\) 更近,然后看 \(b_2\) 就要离 \(a_3\) 比离 \(a_2\) 更近 ...... 到最后 \(b_{n-1}\) 要离 \(a_n\) 更近,那 \(b_n\) 必然会引爆 \(a_n\),与假设不符,矛盾。

所以这个下界一定能构造出,然后考虑每次怎么找一个能引爆 \(a_i\)\(b_i\).就考虑 \(b_i\) 最近的要满足是 \(a_i\) 的话,需要一个区间 \([l,r]\) 里的 \(a_j\) 都被删掉,那么就线段树优化建图,然后拓扑排序。

可以不用这么麻烦!维护一个栈,从前往后枚举 \(i\),如果 \(a_i<b_i\) 就压入栈;如果 \(a_i>b_i\)。就不断检查 \(b_t\)\(a_t\) 比离 \(a_i\) 更近的话就弹出 \(t\) 并且把它干碎;否则就可以干碎 \(i\) 然后 break 了。

很好理解为什么是对的,但我觉得这怎么想到的啊!

dhw:
我最后可能是
就单纯觉得如果一开始全是ai>bi就好了
或者最后全是ai<bi
但是做不到
于是考虑一边压进栈一边解决
发现就可以了。

希望我们常人能够理解大师的思路!

J

先别把问题转化成两个前缀!

没什么想法!枚举算法!扫描线没救!莫队看上去很慢!分治!按照纵坐标分治一下!

考虑跨过中线的,如果左半部分红的最大值,在内外哪侧,和右半部分蓝的最大值,在内外两侧,相同时,那么肯定是它俩对答案贡献。

然后发现就算它们并不是同在内侧或者同在外侧,那么对答案产生贡献的点对,也一定包含左红最大值和右蓝最大值。

把所有可能的 \(\mathcal{O}(n\log n)\) 个点对拉出来(支配对的套路),答案一定出现在它们之中,那么问题就变成 2-side max 了。

cf blog 里面一个 \(\mathcal{O}(n)\) 支配对的方法是:

  • 对每个红点,找纵坐标大于它的最优的蓝点;
  • 对每个蓝点,找纵坐标小于它的最优的红点;
  • 将红点按照纵坐标排序,对于权值的每个前缀最大值,对于下一个前缀最大值的纵坐标 \(y\),找纵坐标比 \(y\) 大的最优的蓝点。

为什么是对的!我还不懂!后面的英文看不懂了!

posted @ 2023-03-29 20:55  do_while_true  阅读(77)  评论(0编辑  收藏  举报