0%

2025 河南省赛——Problem C. Toxel 与宝可梦图鉴(珂朵莉树+值域线段树维护全局信息)(因为这道题目,可以设计珂朵莉树无这个查询操作,只有 assign 操作,因此严格 O(nlogn))(区间等差数列赋值,全局查询最小众数)

2025 National Invitational of CCPC (Zhengzhou), 2025 CCPC Henan Provincial Collegiate Programming Contest

题目大意

给定一个长度为 nn 的数组 aa,初始时第 ii 个位置的值为 aia_i1ain1 \le a_i \le n)。共有 mm 次操作,每次操作给定 l,r,dl, r, d,将区间 [l,r][l, r] 内的值依次替换为 d,d+1,,d+rld, d+1, \ldots, d+r-l

在初始状态以及每次操作后,输出数组中出现次数最多的值及其出现次数。若有多个值出现次数相同,输出其中编号最小的。

多组测试数据,TT 组,保证 n2×105\sum n \le 2 \times 10^5m2×105\sum m \le 2 \times 10^5

样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
输入:
3
3 3
1 2 3
1 1 2
2 2 3
3 3 1
1 1
1
1 1 1
8 8
7 6 6 4 3 8 5 3
4 4 4
6 8 6
1 1 7
4 7 4
6 7 6
2 7 5
1 5 7
1 6 8

输出:
1 1
2 2
3 2
1 1
1 1
1 1
3 2
3 2
6 3
6 3
6 3
6 3
7 2
8 2
8 2

样例解释(第一组数据)

初始数组为 [1,2,3][1, 2, 3],三个值各出现 11 次,输出最小编号 11,次数 11

11 次操作 l=1,r=1,d=2l=1, r=1, d=2:将位置 11 替换为 22,数组变为 [2,2,3][2, 2, 3],值 22 出现 22 次最多,输出 2 22\ 2

22 次操作 l=2,r=2,d=3l=2, r=2, d=3:将位置 22 替换为 33,数组变为 [2,3,3][2, 3, 3],值 33 出现 22 次最多,输出 3 23\ 2

33 次操作 l=3,r=3,d=1l=3, r=3, d=1:将位置 33 替换为 11,数组变为 [2,3,1][2, 3, 1],三个值各出现 11 次,输出最小编号 11,次数 11

思路讲解

我看了一下,宝可梦这道题目珂朵莉树不会被卡的原因是因为全局查询,可以通过维护全局信息解决这个问题。
好像只要改成区间查询,区间修改,珂朵莉树一定会被卡

珂朵莉树的时间复杂度过于玄学了,我还是想用这个时间复杂度更加确定的算法解决问题。

还是学一下珂朵莉树吧,好像这道题目只能用珂朵莉树,或者至少用珂朵莉树最简单,其他各种各样,形形色色的数据结构,都不是说特别好。

image

不难发现,珂朵莉树只有 assign 操作,肯定是 O(nlogn)O(n\log n),当然,这个东西没有那么显然,但是不难理解。因为 l,r 越大,需要遍历的区间就越多,但是一次性也把很多区间给整合在一起了。区间小嘛,一共就不遍历几个区间,何谈什么复杂度?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class F>
void assign(ll l, ll r, ll val, F on_change) {
// 这个顺序对于我们 mp 珂朵莉树实现无所谓
split(r + 1);
split(l);
auto it = mp.lower_bound(l);
while (it != mp.end() && it->first <= r) {
ll st=it->first;
auto [ed,val]=it->second;
// 具体怎么调用看你的 on_change() 实现,一般是一个全局操作
on_change();
it = mp.erase(it);
}
mp[l]={r,val};
on_change();
}

我感觉那种只问一次,或者像这种全局询问的,都非常适合珂朵莉树

AC代码

AC
https://codeforces.com/gym/105941/submission/368114371

starsilk 的代码

https://codeforces.com/gym/105941/submission/322881549

心路历程(WA,TLE,MLE……)