我们先来看看简单版本的想法,非常具有启发性
大致的思路见这篇文章
下面是对这篇文章具体操作的阐释
我们先将所有区间按照左端点单调递增排序,并统计每一个区间中 c i = 1 c_i=1 ci=1的个数(这个直接用前缀和就好了,设 s u m [ i ] [ j ] sum[i][j] sum[i][j]表示前 i i i个数中 c k = j c_k=j ck=j的个数),枚举其中一个区间(设为 [ l , r ] [l,r] [l,r]),然后分类讨论(要敢于分类讨论)
如果另一个区间(这里我们指的另一个区间是编号比当前区间更前面的区间)与其不相交,那么我们查询右端点小于 l l l的所有区间的 c i = 1 c_i=1 ci=1的个数最大的区间就好了。我们设 g [ i ] g[i] g[i]表示区间右端点小于 i i i的所有区间的 c i = 1 c_i=1 ci=1的个数最大值
如果另一个区间相交,那么我们枚举当前区间 c i = 2 c_i=2 ci=2的位置(这个可以用vector预处理),并找出另一个区间,进行分类讨论就好了
update 2024.7.25
重新做这道题目做出来了
由于 k = 2 k=2 k=2,所以可以想到“北大ACM队的远足”的技巧,于是可以解决区间不相交的情况,对于相交的情况,转换对象,考虑每个刚好被覆盖了两次的城市即可
题解的统计方法可以学,我是这么想的:从左到右循环每个城市,开一个数据结构,对于当前城市,假设数据结构中存的是覆盖了这个城市的区间(也就是右端点大于当前城市,左端点小于当前城市),那么从这个城市到下一个城市的时候,只需要从数据结构中删除以当前城市为右端点的区间以及加入以当前城市为左端点的区间就好了
然而在写代码的过程中却发现一个问题,如果只按上面这样分类讨论,我们是会遗漏一种情况的,就是如果两个区间重合,但是重合部分没有 2 2 2,但是我们仍然可以算没有重合的部分的 1 1 1的个数
目前想到的办法就是得到覆盖当前城市的所有区间的时候,记录这些区间最大的右端点和最小的左端点,然后统计他们之间的 1 1 1的个数;这么做的话就需要重新排序,然后还要排序回去(但是排序回去就必须给区间加上id,否则的话排序回去可能与最开始的排序顺序不同)