题目链接
题意:现在有n只虫,每只虫的位置都用一个横竖坐标表示,现在有一种杀虫剂,这种杀虫剂投放到某一点,能将所在行和列的所有虫杀死,现在让求出只投放一次杀虫剂,最多能杀多少只虫和在满足杀最多只虫的情况下,有多少种方式能杀这么多只虫。
题解:因为没有给定这个坐标系到底有多大,所以肯定不能暴力枚举,首先我们考虑虫都在一行或一列的情况,肯定只有一种情况,杀n只虫,还有就是每行每列都只有一只(例如对角线的情况),我们最多能杀两只,有n*(n-1)/2种情况。然后就是常规做法了,我们将虫最多和次多的行和列全部记录下来有多少种(为啥要记录最多和次多,因为可能有多个最多的,但是有些行和列有点重合就需要减去一个)。然后就根据点来判断,细节看代码。
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int mod = 998244353;
const int maxn = 1e5 + 5;
const int inf = 1e9;
const long long onf = 1e18;
#define me(a, b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI 3.14159265358979323846
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
map<int, int> sx, sy;
int n;
struct node {
int x, y;
} a[maxn];
void work() {
scanf("%d", &n);
sx.clear(), sy.clear();
int Maxx = 0, Maxy = 0;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i].x, &a[i].y);
sx[a[i].x]++;
sy[a[i].y]++;
Maxx = max(Maxx, sx[a[i].x]);
Maxy = max(Maxy, sy[a[i].y]);
}
if (sx.size() == 1 || sy.size() == 1) {
printf("%d 1\n", n);
return;
}
if (Maxx == 1 && Maxy == 1) {
printf("2 %lld\n", (ll) n * (n - 1) / 2);
return;
}
ll fix = 0, sex = 0, fiy = 0, sey = 0;
for (auto it:sx) {
if (it.second == Maxx)///记录最多点行的数目。
fix++;
else if (it.second == Maxx - 1)///记录次多点行的数目。
sex++;
}
for (auto it:sy) {
if (it.second == Maxy)///记录最多点列的数目。
fiy++;
else if (it.second == Maxy - 1)///记录次多点列的数目。
sey++;
}
ll ans1 = fix * fiy;///求出能杀Maxx+Maxy的虫组成的方式有多少种
ll ans2 = fix * sey + fiy * sex;///求出能杀Maxx+Maxy-1的虫组成的方式有多少种
for (int i = 1; i <= n; i++) {
int x = a[i].x, y = a[i].y;
if (sx[x] + sy[y] == Maxx + Maxy) {
///因为这里我们枚举的是每只虫,要是满足这个等式,说明这种情况只能杀Maxx+Maxy-1只虫
ans1--, ans2++;
} else if (sx[x] + sy[y] == Maxx + Maxy - 1)///与上面情况同理,满足这个等式只能杀Maxx+Maxy-2只虫
ans2--;
}
if (!ans1)///要是最后ans1减成0了,说明能杀Maxx+Maxy的虫每种方式行和列都重复了一个。
printf("%d %lld\n", Maxx + Maxy - 1, ans2);
else
printf("%d %lld\n", Maxx + Maxy, ans1);
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("1.in", "r", stdin);
#endif
int t = 1, Case = 1;
cin >> t;
while (t--) {
printf("Case %d: ", Case++);
work();
}
return 0;
}