题面链接:https://ac.nowcoder.com/acm/contest/890/F
题意:给定n个气球分布在一个二维矩阵之中,现在可以打6枪,横向打3枪,纵向打三枪,能打掉多少气球。规定横向和纵向相邻的两枪距离必须为r。
思路:提前将每一行有哪些列上有气球分别存入数组。然后在以列为单位建立线段树维护一个列和左右距离为r的三列气球总数的max。然后枚举行如果取 i 行为三行的中间那个行 能打掉多少气球。然后查询这三行的气球在哪一列。在线段树上去除。然后再查一次所有列的max 即是枚举到 i 行的最优 与ans取max
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
typedef long long ll;
ll tree[200050*4];
int n;
int n_ = 1;
void up(int index,ll num){
index += n_-1;
tree[index] += num;
while(index){
index = (index-1)/2;
tree[index] = max(tree[index*2+1],tree[index*2+2]);
}
}
void init(){
int len =(int)2e5+50;
while(n_<len) n_*=2;
}
vector<int> G[200050];
int a[200050];
int main()
{
int r;
cin>>n>>r;
init();
int maxx=0;
int maxy=0;
for(int i=0;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
maxx = max(maxx,x);
maxy = max(maxy,y);
G[y].push_back(x);
if(x-r>=0){
up(x-r,1);
}
up(x,1);
up(x+r,1);
a[y]++;
}
int ans = 0;
for(int i=0;i<maxy+1;i++){
int res = a[i];
if(i-r>=0) res+=a[i-r];
res+=a[i+r];
if(i-r>=0){
for(auto tmp:G[i-r]){
if(tmp-r>=0) up(tmp-r,-1);
up(tmp,-1);
up(tmp+r,-1);
}
}
for(auto tmp:G[i]){
if(tmp-r>=0) up(tmp-r,-1);
up(tmp,-1);
up(tmp+r,-1);
}
for(auto tmp:G[i+r]){
if(tmp-r>=0) up(tmp-r,-1);
up(tmp,-1);
up(tmp+r,-1);
}
res += tree[0];
if(i-r>=0){
for(auto tmp:G[i-r]){
if(tmp-r>=0) up(tmp-r,1);
up(tmp,1);
up(tmp+r,1);
}
}
for(auto tmp:G[i]){
if(tmp-r>=0) up(tmp-r,1);
up(tmp,1);
up(tmp+r,1);
}
for(auto tmp:G[i+r]){
if(tmp-r>=0) up(tmp-r,1);
up(tmp,1);
up(tmp+r,1);
}
ans = max(ans,res);
}
cout<<ans;
return 0;
}