zoukankan      html  css  js  c++  java
  • 【ICPC2019银川站】K

    原题:

    题意:

    给你两个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("
    ");
    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
    ",ans);
    73     return 0;
    74 }
    View Code
  • 相关阅读:
    Java线程状态和关闭线程的正确姿势
    Eclipse最全的编码设置
    Maven中的src/test/java颜色不正常
    web.xml 各版本的 Schema 头部声明
    程序员面试系列
    几款强大的网页生成工具
    endnoteX9批量导入enw
    关于Ubuntu16.04里安装elasticsearch-head显示集群健康值未连接的问题
    U盘做了系统盘,写入如硬盘映像过程中终止,怎么格式化硬盘重新写入?
    使用jupyter notebook出现kernel error
  • 原文地址:https://www.cnblogs.com/cdcq/p/14076458.html
Copyright © 2011-2022 走看看