AT_arc182_a [ARC182A] Chmax Rush!题解

ARC182A Chmax Rush!

一个比较糖的做法。

考虑如果第 i i i 次操作选择向左进行操作,则对于 j < i j<i j<i 且 V j > V i V_j>V_i Vj>Vi 的操作 j j j,一定有 P j > P i P_j>P_i Pj>Pi(否则无论第 j j j 次操作向左还是向右第 i i i 次操作都无法向左走),且对于这些操作 j j j,我们要求他们必须向右进行操作。

于是有一个很糖的 DP,设 d p i , j , 0 / 1 dp_{i,j,0/1} dpi,j,0/1 表示考虑前 i i i 个操作,所有 V ≥ j V \ge j V≥j 的操作全部向左/全部向右的方案数。

时间复杂度 O ( N Q ) O(NQ) O(NQ)。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int n,q,cnt=0;
struct js
{
	int p,v,id,vv;
}a[5005];
bool cmp(js x,js y)
{
	return x.vv<y.vv;
}
bool cmpp(js x,js y)
{
	return x.id<y.id;
}
int dp[5005][5005][2],dpp[5005];
int tree[5005],tr[5005];
int lowbit(int x){return x&(-x);}
void update(int x,int y)
{
	for(int i=x;i<=cnt;i+=lowbit(i)) tree[i]=max(tree[i],y),tr[i]=min(tr[i],y);
}
int query(int x)
{
	int res=0;
	for(int i=x;i;i-=lowbit(i)) res=max(res,tree[i]);
	return res;
}
int qu(int x)
{
	int res=1e9+5;
	for(int i=x;i;i-=lowbit(i)) res=min(res,tr[i]);
	return res;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>q;
	for(int i=1;i<=q;i++) 
	{
		cin>>a[i].p>>a[i].vv;
		a[i].id=i;
	}
	sort(a+1,a+1+q,cmp);
	for(int i=1;i<=q;i++)
		if(i==1||a[i].vv!=a[i-1].vv) cnt++,a[i].v=cnt;
		else a[i].v=cnt;
	sort(a+1,a+1+q,cmpp);
	memset(tr,127,sizeof(tr));
	dpp[0]=1;
	for(int i=0;i<=cnt;i++) dp[0][i][0]=dp[0][i][1]=1;
	for(int i=1;i<=q;i++)
	{
		a[i].v=cnt-a[i].v+1;
		if(query(a[i].v-1)<a[i].p) dpp[i]=(dpp[i]+dp[i-1][a[i].v-1][0])%mod;	
		if(qu(a[i].v-1)>a[i].p) dpp[i]=(dpp[i]+dp[i-1][a[i].v-1][1])%mod;
		for(int j=0;j<=cnt;j++)
			if(j<a[i].v)
			{
				if(query(a[i].v-1)==0||query(j)==0) 	dp[i][j][0]=dpp[i];
				else if(query(a[i].v-1)<a[i].p) dp[i][j][0]=(dp[i][j][0]+dp[i-1][a[i].v-1][0])%mod;
				if(query(a[i].v-1)==0||query(j)==0) 	dp[i][j][1]=dpp[i];
				else if(qu(a[i].v-1)>a[i].p) dp[i][j][1]=(dp[i][j][1]+dp[i-1][a[i].v-1][1])%mod;
			}
			else
			{
				if(query(a[i].v-1)==0) 
				{
					dp[i][j][0]=dp[i-1][j][0];
					dp[i][j][1]=dp[i-1][j][1];
				}
			}
		update(a[i].v,a[i].p);
	}
	cout<<dpp[q];
	return 0;
} 
相关推荐
微尘hjx7 小时前
【ByteTrack 04】多轨迹算法ByteTrack改进点
算法·yolo·目标检测·目标跟踪·bytetrack·ultralytics·车跟踪
dtq04248 小时前
C++小案例 - 日志实战
开发语言·c++
路灯上の马陈9 小时前
二叉树的定义与性质
数据结构·二叉树·树结构·1024程序员节
码匠许师傅9 小时前
【C++三方组件】Qt 概览:桌面 C++ 的事实标准与许可证三轨
开发语言·c++·qt
码匠许师傅10 小时前
【C++三方组件】POCO:跨平台系统编程全家桶
开发语言·c++
小蒋观天下11 小时前
雷击与浪涌防护:前端SPD选型、接地网误区,接地不当反而引入干扰
深度学习·算法·机器学习
Bshaya_12 小时前
红黑树详解:概念、规则与插入实现
数据结构·红黑树·二叉搜索树·平衡树·插入逻辑
WBluuue13 小时前
数据结构与算法:分块(一):块状数组、块状链表
数据结构·c++·算法·链表
路灯上の马陈14 小时前
数据结构-树
数据结构·1024程序员节