专栏文章

ARC184D Erase Balls 2D 题解

AT_arc184_d题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minhdw6v
此快照首次捕获于
2025/12/02 02:26
3 个月前
此快照最后确认于
2025/12/02 02:26
3 个月前
查看原文
将所有球按照 XiX_i 排序,那么第 ii 个球满足 Xi=iX_i=i。显然选择的球的顺序并不重要,我们只需要明确哪些球被选了。为了方便,我们在 (0,n+1)(0,n+1)(n+1,0)(n+1,0) 处各添加一个球,并强制选择这两个球。
设选择的球所组成的集合为 S={a1,a2,,am} (0=a1<a2<<am=n+1)S=\{a_1,a_2,\dots,a_m\}\ (0=a_1 \lt a_2 \lt \dots \lt a_m=n+1),那么显然有 Ya1>Ya2>>YamY_{a_1}\gt Y_{a_2}\gt \dots \gt Y_{a_m}
设剩余的球所组成的集合为 f(S)f(S)
  • 对于 uf(S)u \in f(S)x∉f(S)x \not\in f(S),设 aj<u<aj+1a_j \lt u \lt a_{j+1},则显然有 Yaj>Yu>Yaj+1Y_{a_j}\gt Y_u \gt Y_{a_{j+1}}
  • 对于 v∉f(S)v \not\in f(S),设 aj<v<aj+1a_j \lt v \lt a_{j+1},则显然有 Yaj<YvY_{a_j} \lt Y_vYv<Yaj+1Y_v \lt Y_{a_{j+1}}
直接对本质不同的 f(S)f(S) 进行计数比较困难,因此可以转化计数对象,对选择的球所组成的集合 SS 进行计数。
显然不漏容易做到,于是问题变成了如何做到不重。考虑把 f(S)f(S) 的贡献转化到满足下列条件的集合 TT 上:
  • f(T)=f(S)f(T)=f(S)
  • 对于任意 u∉Tu \not\in Tf({u}T)f(S)f\big(\{u\} \cup T\big) \ne f(S);换句话说,即再选择任意一个球都会导致 f(T)f(T) 变化。
显然满足条件的集合 TT 是唯一的,因为了第二个条件相当于要求了集合 TT 是极大的。
于是现在只需要统计有多少个集合 TT 满足上面的条件即可。设 fif_i 表示考虑完前 ii 个球且选择了第 ii 个球的满足条件的集合 TT 的数量。转移时枚举 0j<i0 \le j \lt iYj>YiY_j \gt Y_i 的整数 jj,表示上一个选择的球为 jj,判断是否能从 jj 转移到 ii
  • 若存在 j<k<ij \lt k \lt i,使得对于任意 j<u<kj \lt u \lt k 都不满足 Yi<Yu<YkY_i \lt Y_u \lt Y_k 且对于任意 k<v<ik \lt v \lt i 都不满足 Yk<Yv<YjY_k \lt Y_v \lt Y_j(即选择 kk 不会导致 f(T)f(T) 变化),则不能从 jj 转移到 ii,否则可以从 jj 转移到 ii
于是做一个二维前缀和即可 O(n)\mathcal O(n) 检验是否能从 jj 转移到 ii。总时间复杂度 O(n3)\mathcal O(n^3)
C
const int N=305,mod=998244353;
int n,v[N],s[N][N],f[N];
void add(int &a,int b){
	a+=b;
	if(a>=mod) a-=mod;
}
bool check(int ax,int ay,int bx,int by){
	return s[ax][ay]-s[ax][by-1]-s[bx-1][ay]+s[bx-1][by-1]==1;
}
void solve(){
	cin>>n,s[1][n+2]++,s[n+2][1]++,v[1]=n+2,v[n+2]=1;
	for(int i=1,x,y;i<=n;i++) cin>>x>>y,x++,y++,v[x]=y,s[x][y]++;
	for(int x=1;x<=n+2;x++) for(int y=1;y<=n+2;y++) s[x][y]=s[x][y]+s[x-1][y]+s[x][y-1]-s[x-1][y-1];
	f[1]=1;
	for(int i=2;i<=n+2;i++){
		for(int j=i-1;j>=1;j--){
			if(v[j]<v[i]) continue; 
			bool flag=1;
			for(int k=j+1;k<i;k++){
				if(check(k,v[k],j,v[i])&&check(i,v[j],k,v[k])){
					flag=0;
					break;
				}
			}
			if(flag) add(f[i],f[j]);
		}
	}
	cout<<f[n+2]<<endl;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...