三体系列NOIP模拟赛----执剑人

这道题又是超级贪心优化线段树之类的东西

代码没有存,,,就讲一下思路

首先是60分的贪心算法

考虑这样一个贪心:

先从左往右扫,如果某一时刻不满足要求,则需要删除前面中某一个支持对方的人。我们贪心地选择删除当前时刻访问的人(肯定是支持对方),然后继续往后扫。

然后再从右往左扫,作相同的操作。

直观地理解是这样的:我们尽量删除靠右的人,使得从右往左扫时少删除一些人。

可以采用交换论证法证明这贪心是对的。

利用这个贪心的思路

思考线段树的优化做法

首先我们可以发现从左往右扫完,从右往左扫的这个过程可以不用实现出来。只需要求出右端点开始的最小后缀和的相反数即可。

然后我们发现,如果两个询问区间拥有相同的左端点,则只需要作一次从左往右扫的工作。这使我们想到要离线化解决问题。

我们将询问按左端点排序,按照左端点从大到小的顺序求解询问。

如果已知从 i 开始向右扫需要删除那些结点,则从 i-1 开始向右扫需要删除那些结点可以快速求出。具体来说,如果i-1是支持者,则左数第一个被删除的结点与它抵消;如果i-1是反对者,则加入被删除的结点里。

该过程可以用栈维护。

²通过在栈里面二分,我们可以知道区间[l, r]在从左往右扫时需要删除的结点数量。

²现在问题就是求解以 r 为端点的最小后缀和。

²这个东西可以用块状数组O(sqrt(N))维护(这就是80%算法的由来),更好的方法应该是用线段树O(log(N))维护

²于是该题就在O((N+Q)logN)的时间复杂度内解决了。

代码我也是写的很辛苦的

可惜忘了存,因为忘了将查询的与0取max而改了好久

希望各位不要重蹈覆辙

猜你喜欢

转载自blog.csdn.net/ENESAMA/article/details/82963129