题目 | Monocarp and the Set
Educational Codeforces Round 156 (Rated for Div. 2)
D. Monocarp and the Set
https://codeforces.com/contest/1886/problem/D
2 seconds / 256 megabytes
standard input / standard output
Problem
Monocarp has
Every time Monocarp adds an element into the set except for the first time, he writes out a character:
- if the element Monocarp is trying to insert becomes the maximum element in the set, Monocarp writes out the character >;
- if the element Monocarp is trying to insert becomes the minimum element in the set, Monocarp writes out the character <;
- if none of the above, Monocarp writes out the character ?.
You are given a string
— replace with the character .
Both before processing the queries and after each query, you have to calculate the number of different ways to order the integers
Input
The first line contains two integers
The second line contains the string
Then
Output
Both before processing the queries and after each query, print one integer — the number of ways to order the integers
Examples
Input
6 4
<?>?>
1 ?
4 <
5 <
1 >
Output
3
0
0
0
1
Input
2 2
>
1 ?
1 <
Output
1
0
1
Note
In the first example, there are three possible orderings before all queries:
; ; .
After the last query, there is only one possible ordering:
.
题解
初始情况
逆向思维考虑,初始集合内完整地包含数字
- 如果
:删除集合中最大值,只有 种情况。 - 如果
:删除集合中最小值,只有 种情况。 - 如果
:删除集合中任意非最值,有 种情况。
要获得情况数的话,只需要将每次操作的情况数累乘就好了,并不需要考虑具体的操作数是多少,并且每次操作之间是独立的。
综上,要计算初始情况的情况数,只需
后续操作
后续操作每次会修改操作序列的一位,通过上面的分析可以知道,修改后只有这一次的情况数会改变,那么对答案乘除即可:
- 如果
由>
/<
变成?
,那么情况数应当 . - 如果
由?
变成>
/<
,那么情况数应当 .
由于答案对
非法情况
对于一个操作序列
- 第二次插入时,如果插入数比第一次大,则
- 第二次插入时,如果插入数比第一次小,则
因此,对于一个操作序列,?
,因此直接判断第一位即可,如果为 ?
则不合法, 应当输出 0.
代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
constexpr int MOD = 998244353;
int qpow(int a, int b)
{
a %= MOD;
int ans = 1;
while (b)
{
if (b % 2)
ans = ans * a % MOD;
a = a * a % MOD;
b /= 2;
}
return ans;
}
void solve()
{
int n, m;
cin >> n >> m;
string s;
cin >> s;
int ans = 1;
for (int i = 1; i < s.size(); i++)
if (s[i] == '?')
ans = ans * i % MOD;
cout << (s[0] == '?' ? 0 : ans) << endl;
for (int i = 0; i < m; i++)
{
int x;
char c;
cin >> x >> c;
x--;
if (x)
{
if (s[x] == '?' && c != '?')
ans = ans * qpow(x, MOD - 2) % MOD;
else if (s[x] != '?' && c == '?')
ans = ans * x % MOD;
}
s[x] = c;
cout << (s[0] == '?' ? 0 : ans) << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi