P9413 题解

P9413 「NnOI R1-T2」风屿

题目大意

给定两个长度分别为 $n$,$m$ 的数组 $a$、$b$,以及一个满足 $g_{i,j} = a_i + b_j$ 的大小为 $n \times m$ 的矩阵 $g$。

定义岛 $ (x,y) $ 和 $ (z,w) $ 相邻当且仅当 $ |x-z|+|y-w|=1 $,定义 $ (x,y) $ 和 $ (z,w) $ 连通当且仅当两种情况至少有一种满足:

  • $ (x,y),(z,w) $ 相邻,且 $ g_{x,y}=g_{z,w} $。

  • 存在另一个岛 $ (u,v) $ 使得 $ (x,y) $ 和 $ (u,v) $ 连通且 $ (u,v) $ 和 $ (z,w) $ 连通。

定义无序互异的岛集 $ \{(x_i,y_i)\} $ 为同色连通块,当且仅当岛集中任意两岛连通。

试找出矩阵 $g$ 中最大的同色连通块,并求出该连通块的大小和这样的连通块的个数。

思路

由题面可知定义岛 $ (x,y) $ 和 $ (z,w) $ 相邻当且仅当 $ |x-z|+|y-w|=1 $。显然由此可以推导出:$$ |x-z|+|y-w|=1 \Rightarrow (x = z \wedge y \ne w) \vee (x \ne z \wedge y = w) $$ 显然,要求 $a_x + b_y = a_z + b_w$,则必须满足:$$ (a_x = a_z \wedge b_y \ne b_w) \vee (a_x \ne a_z \wedge b_y = b_w) $$ 此时,只需求 $a$ 和 $b$ 中的最长连续相同区间的长度。

令 $a$ 的最长连续相同区间长度为 $lena$,$b$ 的最长连续相同区间长度为 $lenb$,$a$ 的最大连通块个数为 $tota$,$b$ 的最大连通块个数为 $totb$。由乘法原理可知,最大连通块的大小为 $lena \times lenb$,最大连通块的个数为 $tota \times totb$。

代码

#include <iostream>
#define int long long
#define MAXN 100005
#define MAXM 100005
using namespace std;
int T, n, m;
int a[MAXN], b[MAXM];
int lena, lenb, tota, totb, tmpa, tmpb;
int read(){
    int t = 1, x = 0;char ch = getchar();
    while(!isdigit(ch)){if(ch == '-')t = -1;ch = getchar();}
    while(isdigit(ch)){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
    return x * t;
}
void write(int x){
    if(x < 0){putchar('-');x = -x;}
    if(x >= 10)write(x / 10);
    putchar(x % 10 ^ 48);
}
void solve(){
    n = read();m = read();
    for(int i = 1 ; i <= n ; i ++)a[i] = read();
    for(int i = 1 ; i <= m ; i ++)b[i] = read();
    lena = 1;tmpa = 1;tota = 0;
    lenb = 1;tmpb = 1;totb = 0;
    for(int i = 2 ; i <= n ; i ++){
        if(a[i] == a[i - 1])tmpa++;
        else{lena = max(lena, tmpa);tmpa = 1;}
    }lena = max(lena, tmpa);
    for(int i = 2 ; i <= m ; i ++){
        if(b[i] == b[i - 1])tmpb++;
        else{lenb = max(lenb, tmpb);tmpb = 1;}
    }lenb = max(lenb, tmpb);
    tmpa = 1;tmpb = 1;
    for(int i = 2 ; i <= n ; i ++){
        if(a[i] == a[i - 1])tmpa++;
        else{
            if(tmpa == lena)tota++;
            tmpa = 1;
        }
    }if(tmpa == lena)tota++;
    for(int i = 2 ; i <= m ; i ++){
        if(b[i] == b[i - 1])tmpb++;
        else{
            if(tmpb == lenb)totb++;
            tmpb = 1;
        }
    }if(tmpb == lenb)totb++;
    write(lena * lenb);putchar(' ');
    write(tota * totb);putchar('\n');
}
signed main(){
    T = read();
    while(T--)solve();
    return 0;
}
posted @ 2023-08-26 11:17  tsqtsqtsq  阅读(19)  评论(0)    收藏  举报  来源