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

浙公网安备 33010602011771号