2018 CCPC-Final 2018 I. Cockroaches(技巧题)

题目链接

题意:现在有n只虫,每只虫的位置都用一个横竖坐标表示,现在有一种杀虫剂,这种杀虫剂投放到某一点,能将所在行和列的所有虫杀死,现在让求出只投放一次杀虫剂,最多能杀多少只虫和在满足杀最多只虫的情况下,有多少种方式能杀这么多只虫。

题解:因为没有给定这个坐标系到底有多大,所以肯定不能暴力枚举,首先我们考虑虫都在一行或一列的情况,肯定只有一种情况,杀n只虫,还有就是每行每列都只有一只(例如对角线的情况),我们最多能杀两只,有n*(n-1)/2种情况。然后就是常规做法了,我们将虫最多和次多的行和列全部记录下来有多少种(为啥要记录最多和次多,因为可能有多个最多的,但是有些行和列有点重合就需要减去一个)。然后就根据点来判断,细节看代码。

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include

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 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;
}

 

你可能感兴趣的:(codeforce)