JOI Final 乱做

LOJ3256「JOI 2020 Final」火灾

显然区间询问可以变成前缀询问。

从左往右枚举右端点,维护单调栈,尝试维护每个 \(T\) 的答案。

但是对于一个位置,它往前的后缀最大值个数是 \(O(n)\) 的,所以不能暴力。

按照套路,在一个后缀最大值被弹掉的时候计算它的贡献,那么在询问的时候就只需要考虑在栈里的元素即可。

对于 \(r-i<T\) 的元素只有 \(i\) 最小的那个元素有可能有贡献,而再靠前的元素的贡献可以把 \(pre_r \to r\) 的树建出来之后 dfs 的过程中维护点到根的信息。其中 \(pre_r\) 是前面第一个大于 \(r\) 的位置。

LOJ3013「JOI 2019 Final」硬币收藏

不可能会贪心的,这辈子都不可能会贪心的

先把每个硬币沿着最短路移到矩形内部,这样显然不劣。

然后在矩形内部有 \(2n\) 个球和洞要两两配对。显然可以看做球和洞一起移动。

从左往右贪心。考虑最左边的两个格子,把在同一位置的球和洞匹配掉(显然不劣)之后:

  • 上下都只有洞,那么都往右走。
  • 上下都只有球,同样都往右走。
  • 一边有球一边有洞,不妨设上球下洞,球>洞。如果洞没有被这里的球匹配完,那么就有右边的球走到洞里,这里的球往右边走。可以调整为这里的球往下走,右边的球往上走,代价不变。

所以在第三种情况中,可以直接用球把洞匹配完,然后把球往右移。

进行 \(n\) 步这样的操作即可得到答案。

LOJ3014「JOI 2019 Final」独特的城市

我的想法:

显然,对于一个点,合法的城市全都在它到它的最远点的路径上。而最远点只能是直径端点之一,所以把两个端点分别提为根做一次。

那么此时一个点就只需要关心它到根这条路径上的点了。

这条路径上哪些点是合法的呢?把 从这条路径上的点开始的往下的路径 往上拍,没被拍到的点即为合法的。

在 dfs 的时候维护这个过程。dfs 到 \(x\) 的时候,用一个栈维护路径上所有合法点对应的颜色,每个颜色只记录最浅的位置(因为最浅的位置最不容易被删掉),栈内颜色按最浅的位置的深度排序。

为了求 \(x\) 的答案,只需要二分求栈内深度较浅的不会被子树拍到的颜色有几个。

dfs 进某一个儿子的时候,把其他儿子的子树往上拍的考虑进去,会把栈里的元素弹掉一些,也可以二分求出位置。然后要把自己的颜色尝试加进去。

那么又有一个问题:我怎么知道我的颜色现在是否还在栈里呢?

对每一个颜色记录它在栈中的位置即可,如果位置 \(\le\) 栈的大小那么说明在栈中,否则不在。

加入 \(x\) 的时候会使栈的大小加 1 ,要把原来在这个位置的颜色标记为不在栈中,即把它在栈中的位置定为 \(\infty\)

回溯的时候撤销所有操作。

题解做法:

前面基本上是一样的,还是在于怎么求链上合法的不同颜色个数。

用栈维护没被拍掉的点,用桶维护每种颜色的出现次数。

长链剖分,先往重儿子走(用轻儿子的最大深度弹栈),再往轻儿子走(用重儿子弹栈)。

然后复杂度就对了?就对了?就对了?你在玩我?

如果按我的想法,每次 dfs 之后还撤销,那么复杂度显然是不对的。

但是注意到一个性质:如果往一个儿子走,子树内的链把自己的祖先拍掉了,那么往别的儿子走的时候这些祖先还是要被拍掉的,也就是说它们已经废了。

所以是不用撤销的,只需要 dfs 一个儿子后再把自己加进去一次即可,因为自己是不一定要被拍掉的。

总入栈次数是 \(O(n)\) 的,所以复杂度 \(O(n)\)

LOJ2335「JOI 2017 Final」足球

最怕这种看起来莫名其妙的题了……

不学OI的同学总觉得这种题是最好做的

在最优解中,如果一个人曾经控过球且现在没有控球,那么以后都不可能控球。证明是因为运球和空跑的代价是一样的。

然后我就不会了啊啊啊啊……

可以猜到这么一个做法:把每个位置拆点,分别表示 没人控球、有人控球、在往上/下/左/右飞 ,然后没人控球向有人控球连的边权为 \(C\times 最近的人\) ,跑最短路。

容易发现最优解一定被包含了,但是怎么证明这样跑出来的方案合法呢?具体而言,怎么保证一个人不会产生分身,跑去一个地方踢了一脚,瞬移回原来位置,又去另一个位置踢了一脚呢?

没看到哪里有证明,于是自闭了……

Rose_max 老大给了个证明,不过看不太懂,所以弃了。

LOJ2336「JOI 2017 Final」绳

由于染色的代价和厚度有关,所以可以发现折完再染不如一开始就染好。

考虑一个颜色序列什么时候合法。显然只能有两种颜色。

在每一次折的时候,要么是把边上的颜色连续段长度减 1 ,要么是把对称点所在的连续段长度砍半,且变到边上去,较短的那一边删掉,其他连续段不变。

所以初始状态除了两端的连续段长度都必须是偶数,并且容易证明这是充要条件。

然后这个条件也就等价于对于我们重点关心的那个颜色,每一段长度为偶数,且起始位置的奇偶性相同。

所以对于每一种颜色,枚举起始位置的奇偶性,判断每一段是否要往前/往后生长(可以发现此时即使两段合并了也没有问题,因为不可能重叠),然后在剩下的格子里挑出现次数最多的颜色和它一起。

怎么除了第一步以外每一步都想不到啊 /kk

LOJ2345「JOI 2016 Final」领地

先特判掉一个周期走回原地的情况。

否则,相当于是这个路径每次会向着一个向量的方向平移,最后得到许许多多的路径的交。

把只靠这个向量就可以互相平移到的格子设为一组,每组分别做。显然对于所有组的格子,边界上的被初始路径经过的点数之和是 \(O(n)\) 的。

对于这一组格子,把四个角的被标记的点分别拿出来,然后一个点会覆盖后面连续 \(K\) 个位置,可以变成 \(O(n)\) 个线段,最后再用归并把这 4 组线段求个交即可。

以上是口胡,因为网上没看到有题解。

LOJ2346「JOI 2016 Final」断层

直接维护看起来莫名其妙的,考虑把最后在地面的位置标记一下,倒着做,维护它们原来在哪里。

手画一画就会发现,好像此时每次操作都是对一个前缀/后缀进行操作。

证明:

  • 对于操作 1 ,一个点会往左下滑当且仅当 \(x-y\) 较小,操作结束后被操作的点 \(x-y\) 不变, \(x+y\) 减小。
  • 对于操作 2 ,一个点会往右下滑当且仅当 \(x+y\) 较大,操作结束后被操作的点 \(x+y\) 不变, \(x+y\) 增大。

在初始情况下,点的 \(x-y,x+y\) 都递增,所以任意时刻都是递增的,任意操作都是对一个前缀/后缀进行。

所以就线段树维护一下坐标即可。

LOJ2727「JOI 2015 Final」舞会

显然可以二分答案,变成 01 串。显然编号没有任何用。

考虑操作的过程,相当于每次把最靠前的三个合并成一个丢到最后面去。

一开始模拟一下这个过程,把合并出来的作为三个的父亲,即可建出一棵树。

在树上设 \(dp_x\) 表示让 \(x\) 子树合并出一个 1 要多少个 1 即可。

LOJ2760「JOI 2014 Final」裁剪线

第一眼看上去好像毫无思路,于是考虑扫描线。

从上往下扫,维护被竖线分开的段之间的连通性。

加入一条竖线的时候,把一个段分成两个段,但这两个段是连通的。

删除一条竖线的时候,把相邻的两个段合并,相应的连通性也可能会改变,用并查集维护即可。

加入一条横线的时候,会把一个区间的段删除,换成新的和别的段都不连通的段。其中删除的段中每有一整个连通块被删除则答案加一。

朴素地做好像是 \(O(n^2)\) 的。

把加入横线时加入的段设为 “平凡的” ,加入或删除一条竖线的时候影响的段设为 “特殊的” 。

显然特殊的段的个数是 \(O(n)\) 的,而加入横线的时候可以很容易把平凡的段的贡献算上,对于特殊的段暴力统计,并且特殊的段被横线删掉后就会变成平凡的。

所以数据结构维护一下即可做到 \(O(n\log n)\)

以上都是口胡,网上只看到一篇题解,不过思路似乎是这样的。

LOJ2765「JOI 2013 Final」 冒泡排序

好像和这个基本一模一样。

显然交换之后的代价就是逆序对数;显然在特判掉原本就有序之后,如果交换 \(i<j,h_i>h_j\) ,那么贡献是 \(1+2\sum_{k=i}^j [h_j<h_k<h_i]\)

所以 \(i\) 一定是前缀最大值, \(j\) 一定是后缀最小值。

此时可以证明决策单调性,用分治+主席树在 \(O(n\log^2 n)\) 的复杂度内做出来。

然而另一个做法更暴力也更快……

对于一个点 \((x,h_x)\) ,可以求出哪些 \((i,j)\) 会包含它,显然是个矩形。

那么用扫描线即可得到矩形覆盖的最大值,\(O(n\log n)\)

这篇博客终于更完了……

posted @ 2020-07-18 18:36  p_b_p_b  阅读(1020)  评论(0编辑  收藏  举报