Loading

[gym 225975L] Гирлянда

思路

题意

每次操作一种颜色使其翻转, 求极长亮灯区间个数

首先进行简单转化, 不难发现相邻的同颜色灯泡是没什么意义的, 因此进行缩点
现在变成了这样一种形式
pEMjUE9.png

不难发现极大亮灯区间的计算方式

假设当前有 \(u\) 个亮着的灯, 其中有 \(w\) 条边连接了两个两者的灯\((\)因为先前的缩点, 一定是两个不同的颜色的灯\()\)
那么极大亮灯区间的个数为 \(u - w\)

部分分(出题人提示)

确定颜色数量 k500k \leq 500

不难发现可以预处理出每两种颜色之间的边有多少条, 一次修改只需要枚举颜色做到 O(qk)\mathcal{O} (qk)

然后我把这个做了之后, 竟然没有想到最简单的暴力错失了想到根号分治的机会
你发现这是个数少的处理方式, 就应该去想用大小处理问题的方式

不难发现, 如果一种颜色的灯泡个数少, 我们可以枚举其每个灯泡, 判断连边是否有效即可


现在用逻辑化的语言解释上面的内容
设立阈值 \(B\)

不妨设 \(cnt_k\) 为颜色 \(k\) 的灯泡个数

  • 假设 \(cnt_i \leq B\) , 我们称之为小颜色
  • 假设 \(cnt_i \geq B\) , 我们称之为大颜色

那么我们可以这样思考

  • 当前修改小颜色
    • 枚举小颜色的连边, 判断连边是否有效, 复杂度 \(\mathcal{O} (B)\)
  • 当前修改大颜色
    • 大颜色和大颜色之间的连边
      注意到直接枚举大颜色的连边复杂度不好, 考虑到大颜色个数少, 用个数解决问题
      同特殊性质, 两两大颜色之间处理连边个数, 复杂度 \(\mathcal{O} (\frac{n}{B})\)
    • 大颜色和小颜色之间的连边
      逆向思考, 处理小颜色的时候, 预处理其连边的大颜色开关灯的贡献
      具体的, 如果当前小颜色连向了大颜色, 那么大颜色开灯的贡献就是亮灯有连边小颜色的边数

总结

根号分治的技巧

个数少, 用个数处理问题
个数多, 代表大小少, 用大小处理问题

大小少, 用大小处理问题
大小大, 代表个数少, 用个数处理问题

如果题目中出现了 个数少/大小少, 那么我们推 大小少/个数少 的做法

posted @ 2025-02-19 15:57  Yorg  阅读(30)  评论(0)    收藏  举报