cdcq

梦幻小鱼干

导航

【ICPC2019银川站】K - Largest Common S

原题:

题意:

给你两个n*m的矩阵,在每个矩阵中,元素的值都是1-n*m且互不相同

问你这两个矩阵的最大公共子矩阵有多大

 

首先可以想到由于每个值在一个矩阵只出现一次,因此两个矩阵之间建立了一个映射关系

接着考虑在和子矩阵有关的方面,这个关系有什么性质

可以发现,某个相等子矩阵中每一个元素的偏移量一定相同

因此可以计算左边矩阵每个值到右边矩阵的偏移量

为了方便计算,给每一种偏移量分配一个颜色

问题转化为,给一个颜色矩阵,求一个最大的单色子矩阵

对于有两种颜色的矩阵,可以用单调队列来求,那么对于多种颜色的矩阵呢

可以发现,在某一行的单调队列处理的过程种

如果某个元素和上一个元素颜色不一样,那么就可以直接把队列清空

如果和上一个元素颜色一样,就按照常规单调队列处理

这本质上是利用了不同颜色之间绝对排斥的性质

 

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 struct nds{int x,y,u,v;}c[1100000];
 6 int n,m,a[1100][1100],b[1100][1100];
 7 int bx[1100000],by[1100000];
 8 int d[1100][1100],dt=0;
 9 //nds q[1100][1100];
10 //int hd[1100];
11 nds q[1100];
12 int hd=0;
13 int f[1100][1100];
14 int od[1100000],ot=0;
15 int ans=0;
16 int id(int x,int y){  return (x-1)*m+y-1;}
17 void otd(){
18     for(int i=1;i<=n;++i){
19         for(int j=1;j<=m;++j)  printf("%d ",d[i][j]);
20         printf("\n");
21     }
22 }
23 void sv(int x){
24     hd=0;
25     q[0].x=0,q[0].y=0;
26     for(int i=1;i<=m;++i){
27         if(d[x][i]!=d[x][i-1]){
28             while(hd>0){
29                 ans=max(ans,(i-q[hd-1].x-1)*q[hd].y);
30                 hd--;
31             }
32             q[0].x=i-1;  //attention
33         }
34         else{
35             while(hd>0 && q[hd].y>=f[x][i]){
36                 ans=max(ans,(i-q[hd-1].x-1)*q[hd].y);
37                 hd--;
38             }
39         }
40         q[++hd]=(nds){i,f[x][i],0,0};
41     }
42     while(hd>0){
43         ans=max(ans,(m-q[hd-1].x)*q[hd].y);
44         hd--;
45     }
46 }
47 bool cmp(nds x,nds y){
48     return x.x==y.x ? x.y<y.y : x.x<y.x;
49 }
50 int main(){
51     scanf("%d%d",&n,&m);
52     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)
53         scanf("%d",&a[i][j]);
54     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){
55         scanf("%d",&b[i][j]);
56         bx[b[i][j]]=i;
57         by[b[i][j]]=j;
58     }
59     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)
60         c[id(i,j)+1]=(nds){bx[a[i][j]]-i,by[a[i][j]]-j,i,j};
61     sort(c+1,c+n*m+1,cmp);
62     c[0].x=-1,c[0].y=-1;
63     for(int i=1;i<=n*m;++i){
64         if(c[i].x!=c[i-1].x || c[i].y!=c[i-1].y)  ++dt;
65         d[c[i].u][c[i].v]=dt;
66     }
67     for(int i=1;i<=n;++i)for(int j=1;j<=n;++j){
68         if(d[i][j]==d[i-1][j])  f[i][j]=f[i-1][j]+1;
69         else  f[i][j]=1;
70     }
71     for(int i=1;i<=n;++i)  sv(i);
72     printf("%d\n",ans);
73     return 0;
74 }
View Code

 

posted on 2020-12-02 21:03  cdcq  阅读(228)  评论(0编辑  收藏  举报