[ICPC2025 上海站 L] qoj15325. Yet another permutation problem 题解
考虑 \(a\) 能否生成 \(b\)。先执行分裂,分成若干极小不可再次分割的连续段,满足 \(S(a[l:r])=S(b[l:r])\)。接下来考虑每个连续段,如果退化到单点显然不用管,否则考虑 \(\min,\max\) 的相对关系,如果没有改变就寄了,否则一定要交换,然后进一步分割下去。
令 \(f_{l,r,0/1/2}\) 表示仅考虑 \(a[l:r]\),其中这一段:无变化,\(\min\) 被换为 \(\max\),\(\max\) 被换为 \(\min\),且 \([l,r]\) 本身是无法分割矩形的答案,同理处理一个 \(g\) 表示对这些矩形的合并,即将多叉树变为一个二叉树,每次拼上最前面的矩形即可。
对于 \(f\) 的转移,如果并非单点,那么一定需要执行 \(swap(\min,\max)\) 的操作,令 \(\min,\max\) 的位置分别为 \(p,q\),那么需要枚举新的首个子矩形位置为 \(i\in[p,q)\),从 \(f_{l,i,L}g_{i+1,r,R}\) 进行转移。注意:需要容斥掉,虽然可以 \(swap(\min,\max)\),但是还会进一步分割的 \(b\),这样枚举首个矩形断点在 \(\ge\max(p,q)\) 的范围即可。\(g\) 的转移显然枚举断点 \(i\in[l,r)\),求出左右状态即可。
总时间复杂度 \(\mathcal O(n^3)\)。
提交记录。
#include<bits/stdc++.h>
#define bll __int128
#define ull unsigned long long
#define ll long long
#define uint unsigned
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
#define inf 1000000000
#define infll 1000000000000000000ll
#define pii pair<int,int>
#define rep(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
#define per(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
#define F(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define dF(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define eb emplace_back
#define SZ(x) ((int)x.size())
#define all(x) x.begin(),x.end()
using namespace std;
bool ST;
void fre(){
// freopen(".in","r",stdin),freopen(".out","w",stdout);
}
inline int lowbit(int x){ return x&(-x); }
template<typename T>inline void chkmax(T &x,const T &y){ x=std::max(x,y); }
template<typename T>inline void chkmin(T &x,const T &y){ x=std::min(x,y); }
const int mod=998244353,maxn=505;
inline int add(int x,int y){ return x+y>=mod?x+y-mod:x+y; }
inline int sub(int x,int y){ return x>=y?x-y:x+mod-y; }
inline void inc(int&x,int y){ x=x+y>=mod?x+y-mod:x+y; }
inline void dec(int&x,int y){ x=x>=y?x-y:x+mod-y; }
int n,a[maxn],f[maxn][maxn][3],g[maxn][maxn][3],b[maxn];
int findmn(int l,int r){
int pos=0;
F(i,l,r)if(!pos||b[i]<b[pos])pos=i;
return pos;
}
int findmx(int l,int r){
int pos=0;
F(i,l,r)if(!pos||b[i]>b[pos])pos=i;
return pos;
}
void solve(){
cin>>n;
F(i,1,n)cin>>a[i];
F(i,1,n)F(j,0,2)f[i][i][j]=g[i][i][j]=1;
F(len,2,n)F(l,1,n-len+1){
const int r=l+len-1;
F(i,l,r)b[i]=a[i];
const int p=findmn(l,r),q=findmx(l,r);
if(p<q){
F(i,p,q-1)inc(f[l][r][0],1ll*f[l][i][1]*g[i+1][r][2]%mod);
F(i,q,r-1)dec(f[l][r][0],1ll*f[l][i][0]*g[i+1][r][0]%mod);
} else{
F(i,q,p-1)inc(f[l][r][0],1ll*f[l][i][2]*g[i+1][r][1]%mod);
F(i,p,r-1)dec(f[l][r][0],1ll*f[l][i][0]*g[i+1][r][0]%mod);
}
b[p]=n;
const int x=findmn(l,r);
if(x<p){ // p is argmax, modified
F(i,x,p-1)inc(f[l][r][1],1ll*f[l][i][1]*g[i+1][r][0]%mod);
F(i,p,r-1)dec(f[l][r][1],1ll*f[l][i][1]*g[i+1][r][0]%mod);
} else{
F(i,p,x-1)inc(f[l][r][1],1ll*f[l][i][0]*g[i+1][r][1]%mod);
F(i,x,r-1)dec(f[l][r][1],1ll*f[l][i][1]*g[i+1][r][0]%mod);
}
b[p]=a[p],b[q]=1;
const int y=findmx(l,r);
if(q<y){
F(i,q,y-1)inc(f[l][r][2],1ll*f[l][i][0]*g[i+1][r][2]%mod);
F(i,y,r-1)dec(f[l][r][2],1ll*f[l][i][2]*g[i+1][r][0]%mod);
} else{
F(i,y,q-1)inc(f[l][r][2],1ll*f[l][i][2]*g[i+1][r][0]%mod);
F(i,q,r-1)dec(f[l][r][2],1ll*f[l][i][2]*g[i+1][r][0]%mod);
}
g[l][r][0]=f[l][r][0],g[l][r][1]=f[l][r][1],g[l][r][2]=f[l][r][2];
F(i,l,r-1)inc(g[l][r][0],1ll*f[l][i][0]*g[i+1][r][0]%mod);
F(i,l,p-1)inc(g[l][r][1],1ll*f[l][i][0]*g[i+1][r][1]%mod);
F(i,p,r-1)inc(g[l][r][1],1ll*f[l][i][1]*g[i+1][r][0]%mod);
F(i,l,q-1)inc(g[l][r][2],1ll*f[l][i][0]*g[i+1][r][2]%mod);
F(i,q,r-1)inc(g[l][r][2],1ll*f[l][i][2]*g[i+1][r][0]%mod);
}
cout<<g[1][n][0]<<'\n';
}
bool ED;
signed main(){
fre(),ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int zsy=1;
F(____,1,zsy)solve();
cerr<<"time used: "<<(double)clock()/CLOCKS_PER_SEC<<endl;
cerr<<"memory used: "<<abs(&ST-&ED)/1024.0/1024.0<<" MB"<<endl;
}
// g++ L.cpp -o a -std=c++14 -O2
posted on 2026-01-12 15:45 nullptr_qwq 阅读(1) 评论(0) 收藏 举报
浙公网安备 33010602011771号