本文主要是介绍NOIP-模拟试题之--矩阵,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
2018 NOIP 全套资料下载-提取码:072k
【问题描述】
Mr_he有一个 n* m 的矩阵,并且把1~n* m 这n*m填写在这个矩阵中(注意,每个整数在矩阵出现一次,且仅出现一次)。
Mr_he同时约定一个矩阵权值等于这个子矩阵中的所有数的最小值。
现在Mr_he想知道,在给出的矩阵中,权值为i的子矩阵可能有多少种?
【输入格式】
第一行, 两个整数 N, M。接下来的 N 行, 每行 M 个整数, 表示矩阵中的元素。
【输出格式】
N×M 行, 每行一个整数, 其中第 i 行的整数表示如果小 A 选择的子矩阵权值为 i, 他选择的子矩阵的种类数。
【输入样例】
2 3
2 5 1
6 3 4
【输出样例】
6
4
5
1
1
1
【样例解释】
balabalabala(好吧只是我不想粘图而已AuA)
其他情况不再赘述!
【数据范围】
对于 30%的数据, 1<=N, M<=50;
对于全部的数据, 1<=N, M<=300。
———————————————————————————————————————————————————————
枚举矩阵的上下行(简单来说就是两根线),对于两根线之间形成的矩阵我们发现实际上只有每一列上最小的元素可能是以这两根线为上下界的矩阵中的最小值,所以压缩一下就成了一个序列了。
思考序列上怎么办,可以发现对于一个位置i的元素以其为最小值的线段的端点只可能在L[i]+1和R[i]-1,L[i]表示i左边第一个小于它的元素的下标,R[i]类似。然后以这个点i为最小元素的线段数量就应该是(i-L[i])*(R[i]-i)。这个直接用单调队列就好了。
也就是说对于每一种上下界枚举的情况我们都可以算出这个上下界对某一个元素最终答案的贡献,最后枚举完之后答案自然就出来了。QAQ
AC代码:
#include< iostream>
#include< cstdio>
#include< cstring>
#include< cstdlib>
#include< algorithm>
#include< cmath>
#include< queue>
#include< set>
#include< map>
#include< vector>
#include< cctype>
#define inf 1e9+5
using namespace std;
const int maxn=305;
int N,M,A[maxn][maxn];
int ans[maxn*maxn],minv[maxn];
struct data{ int pos,v; }q[maxn];
int front,rear,L[maxn],R[maxn];
void _scanf(int &x)
{
x=0;
char ch=getchar();
while(ch<‘0’||ch>‘9’) ch=getchar();
while(ch>=‘0’&&ch<=‘9’) x=x10+ch-‘0’,ch=getchar();
}
void data_in()
{
_scanf(N);_scanf(M);
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++) _scanf(A[i][j]);
}
void calc()
{
front=rear=0;
for(int j=1;j<=M;j++)
{
while(front!=rear&&q[rear-1].v>minv[j]) rear–;
L[j]= front!=rear ? q[rear-1].pos : 0;
q[rear++]=(data){j,minv[j]};
}
front=rear=0;
for(int j=M;j>=1;j–)
{
while(front!=rear&&q[rear-1].v>minv[j]) rear–;
R[j]= front!=rear ? q[rear-1].pos : M+1;
q[rear++]=(data){j,minv[j]};
}
}
void work()
{
for(int i=1;i<=N;i++)
{
for(int j=1;j<=M;j++) minv[j]=inf;
for(int ii=i;ii<=N;ii++)
{
for(int j=1;j<=M;j++) minv[j]=min(minv[j],A[ii][j]);
calc();
for(int j=1;j<=M;j++)
ans[minv[j]]+=(j-L[j])(R[j]-j);
}
}
for(int i=1;i<=N*M;i++)
printf("%d\n",ans[i]);
}
int main()
{
freopen(“matrix.in”,“r”,stdin);
freopen(“matrix.out”,“w”,stdout);
data_in();
work();
return 0;
}
原文:https://blog.csdn.net/qq_39439314/article/details/78174152
这篇关于NOIP-模拟试题之--矩阵的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!