(Nowcoder) F.Popping Balloons

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

传送门

题意:一个矩阵上有气球,横着选距离为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;
}








 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值