题解:AT_arc182_a [ARC182A] Chmax Rush!

第一次打 ARC,涨了 2424 分。

思路

我们称 iijj 有限制,当且仅当 i<ji<jvi>vjv_i>v_j

我们枚举 ii,从 ii 往后找 jj,找到第一个被 ii 限制的 jj

接下来我们分类讨论:

  • 如果 pi=pjp_i=p_j,无论如何也没有答案,输出 1-1
  • 如果 pi>pjp_i>p_j,则第 ii 次操作只能往右赋值,第 jj 次只能往左。
  • 如果 pi<pjp_i<p_j,则第 ii 次操作只能往左赋值,第 jj 次只能往右。

找到之后我们赋值 aia_iaia_i 表示第 ii 次赋值的方向),然后退出寻找。当我们枚举到 i=xi=x 时,接着分类:

  • 如果 axa_x 已经被赋值,则把该方向上的所有点都赋值。如果发现无法赋值,输出不可以,退出程序。
  • 如果 axa_x 未被赋值,则分别检验两个方向是否可以赋值,如果没有一个可以,则输出不可以。反之,则将答案乘以可行的方向数量(乘法原理可得)。

于是就做完了。

代码

#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;
}
posted @   Weslie_qwq  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示