1. 程式人生 > >NOIP-模擬試題之--矩陣

NOIP-模擬試題之--矩陣

2018 NOIP 全套資料下載

【問題描述】

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