AtCoder ABC 176E - Bomber

题目链接:https://atcoder.jp/contests/abc176/tasks/abc176_e

题意:给你一个 H ∗ W H*W HW的矩阵,矩阵里有 M M M个目标点,你要在这个个矩阵的任意位置(包括目标点)放一个炸弹,炸弹引爆后会摧毁炸弹同一行,同一列的所有目标点,问你最多可以炸几个目标点。

思路:一个朴实无华的题目,但给你一个相当恶心的数据范围,emmm。在这里插入图片描述
所以这一题我们肯定不能“硬来”,得“智取”(doge)。

从直观上想,我们肯定是要找到所有行里面目标点最多得行,和目标点最多得列,那在这个行,这个列交点处放炸弹,肯定是能使得摧毁的目标点最多。但这就有另一个问题啦,那就是每一行,每一列目标点最多的,可能不止一个呀(个数分别用 n u m 1 num1 num1 n u m 2 num2 num2表示),难道我们用双层 f o r for for循环暴力发所有的组合全部跑一遍嘛?别想啦,出题人随便卡一卡,就能让你过不去…那我们可以回过来想一想,我们开始暴力找的目的是什么?是不是要找一下有没有一个交点不是目标点,那我们在这个交点埋炸弹,那答案是不是就是最大了呢?所以我们可以遍历所有的目标点,找出一共有多少个目标点是交点(用 n u m num num表示),这样如果 n u m 1 ∗ n u m 2 = = n u m num1 * num2 == num num1num2==num,那么答案是行列最大值相加减一就好啦(因为所有的交点都是目标点呀),这样这个问题就可以很快的AC啦。

AC代码:

#define _CRT_SECURE_NO_WARNINGS 1

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <string>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define LL long long
#define pii pair<int,int>
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define pd(x) printf("%d\n",x)
#define plld(x) printf("%lld\n",x)
#define rep(i,a,b) for(int i = (a) ; i <= (b) ; i++)
#define per(i,a,b) for(int i = (a) ; i >= (b) ; i--)
#define mem(a) memset(a,0,sizeof(a))
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define fast_io ios::sync_with_stdio(false)

const LL INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
const int maxn = 3e5 + 7;

map<int,int>cntx,cnty;
pii a[maxn];

int main() {
	fast_io;
	int n,m,num;
	cin >> n >> m >> num;
	int maxx = 0, maxy = 0;
	rep(i,1,num) {
		int x,y;
		cin >> x >> y;
		a[i].first = x, a[i].second = y;
		cntx[x]++, cnty[y]++;
		maxx = max(maxx, cntx[x]), maxy = max(maxy, cnty[y]);
	}
	int numx = 0, numy = 0;
	for(auto temp: cntx) {
		if(temp.second == maxx) numx++;
	}
	for(auto temp: cnty) {
		if(temp.second == maxy) numy++;
	}
	int cnt = 0;
	rep(i,1,num) {
		if(cntx[a[i].first] == maxx && cnty[a[i].second] == maxy) cnt++;
	}
	if(numx * numy == cnt) cout << maxx + maxy - 1 << endl;
	else cout << maxx + maxy << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值