P12406 「CZOI-R3」消除序列 题解
我的方法使用了动态规划和树状数组,可能并不简洁,但题解太简略了,我暂时也不清楚怎么简单地维护题解里的 和 ,其他部分是原题解的详细版本。
首先分析一下操作(方便描述,标了个号):
- 将 循环左移一位。若在进行操作前 ,则消耗 点代价。
- 将 循环右移一位。若在进行操作前 ,则消耗 点代价。
- 交换 。消耗 点代价。
- 若 ,将 循环左移一位,同时令 。不消耗代价。
题目中出现了大量的循环位移操作,实际上可以对其进行简化分析,因为题目要求把 清空,那么我们将每一个 操作当作一个阶段,于是,题目要求按照 数组的顺序完成 个阶段的操作,每个阶段消掉一个数字,消掉数字的顺序就是 数组的顺序(这样,操作 中的循环移位解决掉了)。
移动整个数组并不好处理,因此可以理解为移动环上的指针。于是转化 和 操作,最后的描述可以变为:
令指针 指向 。有如下操作:
- 将指针右移一位,若原指向点不为 ,消耗 点代价。
- 将指针左移一位,若原指向点不为 ,消耗 点代价。
- 交换 。消耗 点代价。
指针要依次移动到 数组标记的每一个位置,完成 个阶段。
注意:移动指针与移动数组相反;指针在 的移动没有代价!
那么,先把每一个阶段要求到达的位置处理出来,这样就没有两个数组了。因为都是排列,所以可以把 中数字位置处理到 数组,即 p[a[i]]=i
,再把 中的每一个数字对应成 中的位置,按顺序记录,详见代码。
入手点是 操作,可以发现,在每一个阶段,一定只会使用 和 操作中的一种,操作 至多 次且在开始(将结尾的操作 归为下一阶段)。考虑到只有操作 有后效性,利用它来设计状态:
- 表示进行过偶数次操作 ,这时 和 操作代价和开始时一样。
- 表示进行过奇数次操作 ,这时 和 操作代价和开始时相反。
设计转移(这应该是比较好想的):
设计边界:
这里重点处理 和 ,具体地,每一个 位置都不算贡献,要求一种可以动态修改和区间查询的数据结构,想到线段树和树状数组。但是在比赛中,线段树由于常数问题(也许)被卡掉了,改用了树状数组,具体逻辑就是把未清空的位置设为 ,清空后改为 ,用区间和处理步数,详见代码。
输出的答案便是 了。
代码如下:
1 |
|
P12406 「CZOI-R3」消除序列 题解
http://shicj.pages.dev/2025/05/04/P12406 「CZOI-R3」消除序列 题解/