传送门
题意:一个矩阵上有气球,横着选距离为r的三行,竖着选距离为r的三行,能打灭的最多气球数。
解:思维还是太弱了,没想到这种暴力的方法,用数组nowC[i]代表中间为第i列的贡献值,全部加入multiset s(和set不同的可以存一样的数据),然后吗我们枚举中间打在第i行,枚举这三行上的点,收到这些点所影响的nowC[i],对s进行修改,最后当前这种选择的贡献就是,横着的总和+s.max; 注意中间的哪一行或者那一列可以在矩阵外,一开始没有考虑到的。
#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=3e5+5;
//il int Add(ll &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
struct node {int x,y;};
vector<node> v[maxn];
int n,r;
multiset<ll> s;
ll srow[maxn],scol[maxn],nowC[maxn];
il void del(int y){
if(y<-r || y>100000+r) return;
s.erase(s.find(nowC[y+r]--));
s.insert(nowC[y+r]);
}
il void add(int y){
if(y<-r || y>100000+r) return;
s.erase(s.find(nowC[y+r]++));
s.insert(nowC[y+r]);
}
int main() {
std::ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>r;
node tp;
for(int i=1; i<=n; ++i) {
cin>>tp.x>>tp.y;
v[tp.x].pb(tp);
srow[tp.x]++;
scol[tp.y]++;
}
ll ans=0,tres=0;
for(int i=-r; i<=100000+r; ++i) { //左移r位
if(i-r>=0) nowC[i+r]+=scol[i-r];
if(i>=0) nowC[i+r]+=scol[i];
nowC[i+r]+=scol[i+r];
s.insert(nowC[i+r]);
}
for(int i=-r; i<=100000+r; i++) {
tres=0;
if(i-r>=0) tres+=srow[i-r];
if(i>=0) tres+=srow[i];
tres+=srow[i+r];
for(int t=i-1-r;t<=i-1+r;t+=r){
if(t<0) continue;
for(int j=0;j<SZ(v[t]);++j){
add(v[t][j].y),add(v[t][j].y-r),add(v[t][j].y+r);
}
}
for(int t=i-r; t<=i+r; t+=r){
if(t<0) continue;
for(int j=0;j<SZ(v[t]);++j){
del(v[t][j].y),del(v[t][j].y-r),del(v[t][j].y+r);
}
}
auto it=s.end();
it--;
ans=max(ans,tres+*it);
}
cout<<ans<<endl;
return 0;
}

本文介绍了一种在矩阵上消除气球的算法策略,通过枚举特定行距内的三行和列距内的三列,计算能消除的最大气球数量。使用了multisets数据结构来高效更新每列的贡献值,最终找到最优解。
644

被折叠的 条评论
为什么被折叠?



