luogu#P4964. 绫小路的特别考试
绫小路的特别考试
题目背景
这世界上「胜利」便是一切。无关乎过程。 要付出多少牺牲都无所谓。只要最后我「胜出」那就行了。
题目描述
一场新的特别考试来临了,这次的考试内容是(wan e de)文化课,但有所不同的是,考试中允许学生使用对讲机。然而,对讲机的接收范围是有限的(每个对讲机都能发送无限远,但是只能接收到接收范围内的信号),所以不是所有学生都能接收到其他同学的广播。
考试时,共有 名学生坐成一排(从左至右依次编号为 ~ ),绫小路自己坐在第 号位置。每名学生都有一个能力值 。绫小路已经给每名学生安排了一个接收范围为 的对讲机。
每名学生可以直接做出难度不超过自身能力值的所有题目,一旦一名学生凭能力做出某道题,他就会把这道题的做法进行广播。一名坐在位置 ,有接收范围为 的对讲机的学生,可以接收到 范围内所有学生的广播,若这个范围内有人公布了做法,则他将会做这道题,并也会把这道题的做法进行广播。
绫小路会问你一些问题:当一道题目难度为 时,有多少学生会做这道题?由于绫小路想隐藏实力,他可能会修改自己的能力值。这两种操作分别用以下两种方式表示:
-
,表示询问当一道题目难度为 时,有多少学生会做这道题。
-
,将绫小路的能力值修改为 ,即将 修改为 。
形式化描述(与上文同义):
给你两个长为 的数列 和 ,以及一个 可修改的位置 。现在有两种操作(共 次):
- 表示一次询问:设 $f_i=\begin{cases}1\quad(w_i\ge x)\\1\quad(\exists\ j \in [i - d_i,\ i + d_i],\ f_j=1)\\ 0\quad(otherwise)\end{cases}$,这里的 定义中引用了 ,所以 是会不断更新的,直到无法继续更新时,计算这次询问的答案为 。
- 表示一次修改:把 修改为 。
输入格式
由于数据量太大,为了避免读入耗时过长,使用伪随机数生成器的方式输入,并强制在线。
建议你忽略输入格式,直接使用下面提供的数据生成器模板,了解具体的生成过程对你来说是不必要的。
第一行,三个正整数 ,分别代表学生的总人数,操作总数和绫小路所在的位置。
第二行,五个整数 $\mathrm{seed},\ \mathrm{mind},\ \mathrm{maxd},\ \mathrm{mfq},\ k$。
此处的 仅用于生成初始的 ,下文中调整 所用的 可能不在 范围内。
接下来的 行,每行两个整数 ,表示调整第 号同学的对讲机接收范围(即 )为 。
若一名同学的对讲机接收范围被调整多次,以最后一次为准。
** 数据生成器模板:**
#include <cstdio>
unsigned long long seed;
int n, m, c, mfq, mind, maxd, k, w[2000001], d[2000001];
inline int randInt() { seed = 99999989 * seed + 1000000007; return seed >> 33; }
void generate()
{
// 在读入种子后生成初始的 w 数组和 d 数组.
for (int i = 1; i <= n; i++) { w[i] = randInt() % n; }
for (int i = 1; i <= n; i++) { d[i] = randInt() % (maxd - mind + 1) + mind; }
}
void getOperation(int lastans, int &opt, int &x)
{
// 生成一次操作的参数 opt 和 x, lastans 表示上一次询问的答案, 初始值为 0.
if ((0ll + randInt() + lastans) % mfq) { opt = 1; } else { opt = 2; }
x = (0ll + randInt() + lastans) % n;
}
int main()
{
scanf("%d %d %d", &n, &m, &c);
scanf("%llu %d %d %d %d", &seed, &mind, &maxd, &mfq, &k);
generate();
for (int i = 1; i <= k; i++)
{
int p, t;
scanf("%d %d", &p, &t);
d[p] = t;
}
// 从这里开始,你可以使用生成的 w 数组和 d 数组.
int lastans = 0, finalans = 0;
for (int i = 1; i <= m; i++)
{
int opt, x;
getOperation(lastans, opt, x);
if (opt == 1)
{
// 在这里执行询问操作,并用答案的表达式替代下面的 ___.
finalans = (finalans * 233ll + ___) % 998244353;
lastans = ___;
}
else
{
// 在这里执行修改操作.
}
}
printf("%d\n", finalans);
return 0;
}
输出格式
令 表示第 次询问(操作 )的答案,$T_i=\begin{cases}(T_{i-1}\times 233+ans_i)\mod 998244353\quad(i\ge 1)\\0\quad(i=0)\end{cases}$
设 表示询问(操作 )的个数,你只需要输出一个整数 。
3 3 2
19720918 0 1 2 0
700
10 10 8
2102036 0 1 4 1
5 2
760521825
1000 1000 126
114321251 1 2 2 0
91977056
提示
你需要用到的变量:
,,。
其它用于生成数据的变量:
,,,,。
样例解释
样例一:
生成得到三名同学的能力值 ,对讲机接收范围 。
第一个操作是 1 1
,询问有多少同学会做难度为 的题。
绫小路(第 名同学)和第 名同学能够独立做出这道题( ,),第 名同学虽然能力不足,但通过对讲机能接收到绫小路广播的做法(),所以他也会做。故 。
第二个操作是 2 0
,修改绫小路(第 名同学)的能力值为 。此时 。
第三个操作是 1 1
,再次询问有多少同学会做难度为 的题。
只有第 名同学能够独立做出(),然而第 名同学和绫小路(第 名同学)都无法接收到他广播的做法(,),做不出来。故 。
综上所述,,,仅输出 即可。
样例二:
生成得到 $w_{1..10} = \{1,\ 6,\ 6,\ 5,\ 3,\ 5,\ 2,\ 7,\ 9,\ 5\}$,$d_{1..10} =\{1,\ 1,\ 1,\ 1,\ 2,\ 0,\ 1,\ 0,\ 1,\ 1\}$。
十次操作及对应结果如下所示:
1 6
,查询操作,,。
2 2
,修改操作, 变为 。
1 7
,查询操作,,。
1 3
,查询操作,,。
2 4
,修改操作, 变为 。
1 3
,查询操作,,。
2 2
,修改操作, 变为 。
1 9
,查询操作,,。
1 0
,查询操作,,。
1 3
,查询操作,,。
仅输出 即可。
样例三:
出题人有足够的良心写出这个样例的解释,可惜版面太小,写不下。