题目链接:点我啊╭(╯^╰)╮
题目大意:
二维平面, n n n 个气球
要求水平方向射三枪,垂直射三枪
每一枪可以打穿一行或一列的所有气球
水平或垂直的相邻枪的距离为 r r r
求能射中的最多气球数
解题思路:
一个气球 ( x , y ) (x,y) (x,y) 在垂直方向上,可以影响到的射击路线是 y ? r , y , y + r y-r,y,y+r y?r,y,y+r
在水平方向上,可以被 x ? r , x , x + r x-r,x,x+r x?r,x,x+r 影响
设 h [ x ] h[x] h[x] 为射击 x x x 行可以影响到的所有气球(三行)
a [ y ] a[y] a[y] 为射击 y y y 列可以影响到的气球数(三列)
开始将所有气球都加入到每一个 a [ y ] a[y] a[y] 中
枚举每一行 x x x ,将该行所能射中的所有气球
所在能被射中的列中删去
维护每一列的最大射中数
时间复杂度: O ( 3 2 × n × 2 + n × 3 ) O(3^2\times n\times 2 + n\times 3) O(32×n×2+n×3)
核心:将三行影响转化为一行影响
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <ll,int>;
const int maxn = 2e5 + 5;
int n, r, ans, mx, a[maxn], cnt[maxn];
vector <int> h[maxn];inline void add(int y){if(y < 0) return;cnt[a[y]++]--;mx = max(mx, a[y]);cnt[a[y]]++;
}inline void del(int y){if(y < 0) return;cnt[a[y]]--;if(cnt[a[y]]==0 && mx==a[y]) mx--;if(a[y]) cnt[--a[y]]++;
}int main() {scanf("%d%d", &n, &r);for(int i=1, x, y; i<=n; i++){scanf("%d%d", &x, &y);h[x].push_back(y);if(x >= r) h[x-r].push_back(y);h[x+r].push_back(y);add(y), add(y-r), add(y+r);}for(int x=0; x<maxn; x++){int res = h[x].size();if(!res) continue;for(auto y : h[x]) del(y), del(y-r), del(y+r);ans = max(ans, res + mx);for(auto y : h[x]) add(y), add(y-r), add(y+r);}printf("%d\n", ans);
}