题解:AT_arc184_d [ARC184D] Erase Balls 2D
posted on 2025-01-19 04:16:34 | under | source
先排序,被操作的点一定是下降子序列,直接算肯定会算重,考虑增强限制去重。
删去的点构成上下两个阶梯,不好处理,故考虑保留的点,是若干首尾相接的矩形。
注意到一个矩形若能被划为两个更小的矩形且点集不变,则会算重,所以要求不能发生这种情况。
现在不会算重了吗?对于最终统计的方案,考虑未被操作的点,若选其一必然多删去点;而操作点若取消操作,要么点集变了,反之不可能被统计(因为操作它点集不变)。
直接计数即可。\(O(n^3)\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 3e2 + 5, mod = 998244353;
int n, s[N][N], f[N];
struct node{int x, y;} a[N];
inline bool chk(int x, int y){
for(int i = x + 1; i < y; ++i)
if(a[x].y > a[i].y && a[i].y > a[y].y && s[x][i] + s[i][y] - 1 == s[x][y]) return false;
return true;
}
signed main(){
cin >> n;
for(int i = 1; i <= n; ++i) scanf("%lld%lld", &a[i].x, &a[i].y);
a[n + 1] = {0, n + 1};
a[n + 2] = {n + 1, 0};
n += 2;
sort(a + 1, a + 1 + n, [](node A, node B){return A.x < B.x;});
for(int i = 1; i <= n; ++i)
for(int j = i + 1; j <= n; ++j)
for(int k = i; k <= j; ++k)
if(a[i].y >= a[k].y && a[k].y >= a[j].y) ++s[i][j];
f[1] = 1;
for(int i = 2; i <= n; ++i)
for(int j = 1; j < i; ++j)
if(a[i].y < a[j].y && chk(j, i)) f[i] = (f[i] + f[j]) % mod;
cout << f[n];
return 0;
}

浙公网安备 33010602011771号