题解:AT_arc182_a [ARC182A] Chmax Rush!
第一次打 ARC,涨了 分。
思路
我们称 对 有限制,当且仅当 且 。
我们枚举 ,从 往后找 ,找到第一个被 限制的 。
接下来我们分类讨论:
- 如果 ,无论如何也没有答案,输出 。
- 如果 ,则第 次操作只能往右赋值,第 次只能往左。
- 如果 ,则第 次操作只能往左赋值,第 次只能往右。
找到之后我们赋值 ( 表示第 次赋值的方向),然后退出寻找。当我们枚举到 时,接着分类:
- 如果 已经被赋值,则把该方向上的所有点都赋值。如果发现无法赋值,输出不可以,退出程序。
- 如果 未被赋值,则分别检验两个方向是否可以赋值,如果没有一个可以,则输出不可以。反之,则将答案乘以可行的方向数量(乘法原理可得)。
于是就做完了。
代码
#include<bits/stdc++.h>
using namespace std;
int n,q;
int a[5005];
int p[5005],v[5005],z[5005];
long long ans=1;
int main() {
scanf("%d%d",&n,&q);
for(int i=1; i<=q; i++) {
scanf("%d%d",&p[i],&v[i]);
z[i]=-1;
}
for(int i=1; i<=q; i++) {
for(int j=i+1; j<=q; j++) {
if(v[i]>v[j]) {
if(p[j]>p[i]) {
if(z[j]==0) {
printf("0");
return 0;
} else z[j]=1;
if(z[i]==1) {
printf("0");
return 0;
} else z[i]=0;
} else {
if(z[j]==1) {
printf("0");
return 0;
} else z[j]=0;
if(z[i]==0) {
printf("0");
return 0;
} else z[i]=1;
}
break;
}
}
if(z[i]==-1) {
int tot=2;
for(int j=p[i]; j>=1; j--) {
if(a[j]>v[i]) {
tot--;
break;
}
a[j]=v[i];
}
for(int j=p[i]; j<=n; j++) {
if(a[j]>v[i]) {
tot--;
break;
}
a[j]=v[i];
}
ans=ans*tot%998244353;
if(tot==0) {
printf("0");
return 0;
}
} else {
if(z[i]==1) {
for(int j=p[i]; j<=n; j++) {
if(a[j]>v[i]) {
printf("0");
return 0;
}
a[j]=v[i];
}
}
else{
for(int j=p[i]; j>=1; j--) {
if(a[j]>v[i]) {
printf("0");
return 0;
}
a[j]=v[i];
}
}
}
}
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号