官方题解
2025-11-03 10:11:13
发布于:浙江
7阅读
0回复
0点赞
题目大意
最初有一个长度 的序列 和 个数对 ,对于每个数对有两种方式执行操作:
- 将 替换为 ,次操作前提是 都小于或等于 。
- 将 替换为 ,次操作前提是 都小于或等于 。
问有多少种不同的操作序列,如果不能全部都执行,则输出 0 。
解题思路
首先我们观察到 ,因此可以尝试使用 的做法实现。
我们称第 个数对操作为 操作,选择第一种执行方式称为向左操作,选择第二种执行方式成为向右操作。
考虑所有两两数对 操作之间的关系,有 ,有以下几种情况:
- 当 时,任意选择即可。
- 当 并且 时,此时这两个操作直接矛盾,答案为 。
- 当 并且 时,操作 必须向左操作,操作 必须向右操作。
- 当 并且 时,操作 必须向右操作,操作 必须向左操作。
对于第三、四种情况,可能会出现不同数对间接矛盾的情况,此时答案也为 。
我们将所有数对操作的可能情况用 进行表示,其中 表示向左向右都可, 表示只能向左, 表示只能向右。
如果所有操作之间没有矛盾,那么答案至少为 ,对于那些上述 的操作,都有两种选择,其他都只有一种选择,不妨设 的操作数为 ,那么答案为 。注意取模。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
const int mod = 998244353;
// dir[i]: 标记第 i 个位置是的方向。
// -1 -- 两个方向都可; 0 -- 向左; 1 -- 向右
int dir[N];
void work(int pos,int x){
if(dir[pos]==-1) dir[pos]=x;
if(dir[pos]!=x){
cout<<0<<endl;
exit(0);
}
}
int main(){
int n,q;cin>>n>>q;
vector<int>p(q+1),v(q+1);
for(int i=1;i<=q;i++){
cin>>p[i]>>v[i];
dir[i]=-1;
}
for(int i=1;i<=q;i++){
for(int j=i+1;j<=q;j++){
// 1. v[i]<=v[j]: i,j 两个位置都可做两种操作
if(v[i]<=v[j]) continue;
// 2. v[i]>v[j] and p[i]=p[j]: 矛盾, 输出0
if(p[i]==p[j]){
cout<<0<<endl;
return 0;
}
// 3. v[i]>v[j] and p[i]>p[j]: i 向右, j 向左 唯一确定
if(p[i]>p[j]){
work(i,1);
work(j,0);
}
// 4. v[i]>v[j] and p[i]<p[j]: i 向左, j 向右 唯一确定
else{
work(i,0);
work(j,1);
}
}
}
int res=1;
for(int i=1;i<=q;i++){
if(dir[i]==-1) res=res*2%mod;
}
cout<<res<<endl;
return 0;
}
这里空空如也






有帮助,赞一个