[AGC056B] Range Argmax 题解

题目链接

点击打开链接

题目解法

这咋想到的???

计数不同的下标序列看上去就很不可做,考虑转化成计数排列
这显然会算重,考虑钦定一种方式,使得一个下标序列仅对应一个序列
我们这样构造:
从大到小加数,找到第一个 pos 满足当前未被删除的且包含 pos 的区间的 x 值均为 pos,然后令 ppos=v,且删去包含 pos 的所有区间

考虑对这个东西计数
我们用区间 dp 的方法,因为删去一个位置之后,显然所有区间会分成不交的 2 部分
如果 [l,r] 区间的最大值在 p 这个位置,考虑分成 [l,p1][p+1,r] 两个子问题做
[p+1,r] 中的所有值一定小于 [l,p1] 中的所有值(这其实是让我们不要乘组合数),其他没有任何限制
主要是 [l,p1] 有限制,即要保证第一个合法的 posp,令 [l,p1] 的最大数的位置为 q,那么合法条件为 p,q 有在 [l,r] 中的区间覆盖

fl,r,p 表示区间 [l,r],最大值的位置 p 的方案数
liml,r,p 为区间在 [l,r] 中的,且包含位置 p 的最左的左端点
转移为:fl,k1,liml,r,k×fk+1,r,k+1+fl,r,k+1fl,r,k

时间复杂度 O(n3)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
const int N=310,P=998244353;
int n,m,lim[N][N][N],f[N][N][N];
inline void inc(int &x,int y){ x+=y;if(x>=P) x-=P;}
int main(){
n=read(),m=read();
F(i,1,n) F(j,1,n) F(k,1,n) lim[i][j][k]=n+1;
F(i,1,m){
int l=read(),r=read();
F(j,l,r) lim[l][r][j]=l;
}
F(len,2,n) F(l,1,n-len+1){
int r=l+len-1;
F(k,l,r) chkmin(lim[l][r][k],min(lim[l+1][r][k],lim[l][r-1][k]));
}
F(i,1,n+1) F(j,1,n+1) f[i][i-1][j]=1;
F(len,1,n) F(l,1,n-len+1){
int r=l+len-1;
DF(k,r,l) f[l][r][k]=1ll*f[l][k-1][lim[l][r][k]]*f[k+1][r][k+1]%P,inc(f[l][r][k],f[l][r][k+1]);
}
printf("%d\n",f[1][n][1]);
return 0;
}
posted @   Farmer_D  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示