题解:AT_abc176_e [ABC176E] Bomber

分析

我们可以用 \(hf\)\(wf\) 分别储存每行的目标数及每列的目标数。

然后我们可以贪心

若想摧毁最多的目标,则选定的位置所在的行是所有行中目标最多的,所在的列是所有列中目标最多的 (感性理解一下)

但是,选定的位置也可能有一个目标。在统计摧毁的目标数时,该目标被算了两次。所以要将该目标被多算的那次减掉。

所以我们可以枚举每个满足条件的位置,然后看是否有一个位置上没有炸弹。

若是,则输出 \(maxh+maxw\)

否则,输出 \(maxh+maxw-1\)

那么代码如下(这里用的是时间复杂度更小的unordered_map):

#include<bits/stdc++.h>
#define int long long
#define fd(i,a,b) for(int i=a;i<=b;i=-~i)
using namespace std;
int h,w,m,hf[300100],wf[300100];
int ans=1,hi,wi,maxh,maxw,cnth,cntw;
int sumh[300100],sumw[300100];
unordered_map < int,unordered_map<int,int> > mp;
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>h>>w>>m;
	fd(i,1,m)
	{
		cin>>hi>>wi;
		hf[hi]++;wf[wi]++;
		maxh=max(hf[hi],maxh);
		maxw=max(wf[wi],maxw);
		mp[hi][wi]++;
	}
	fd(i,1,h)
	{
		if(hf[i]==maxh) sumh[++cnth]=i;
	}
	fd(i,1,w)
	{
		if(wf[i]==maxw) sumw[++cntw]=i;
	}
	fd(i,1,cnth)
	{
		fd(j,1,cntw)
		{
			if(!mp[sumh[i]][sumw[j]])
			{
				ans=0;
				break;
			}
		}
	}
	cout<<maxh+maxw-ans;
	return 0;
}

感谢观看

posted @ 2024-04-02 17:07  whrwlx  阅读(9)  评论(0编辑  收藏  举报