传送门:carpet

题意

有一个n*m的地毯,aij表示地毯每格的元素,bij表示地毯每格的价格,要求选取一块价格最大值最小的地毯,并且这块地毯无限铺开之后,原地毯是其子矩阵。

题解

先找到这个矩阵的最小循环节子矩阵,求一下每行的循环节长度用map记录,取出现次数为m并且循环节长度最小的;每列也求一下循环节长度用map记录,取出现次数为m并且循环节长度最小的;这样就得到了最小的循环节子矩阵。然后问题就变成了求一个p*q的子矩阵最大值的最小值,可以参考这个题 Fake Maxpooling (求得是k*k子矩阵的最大值的和)稍加修改变成求p*q子矩阵的最大值的最小值就好了。这里用到单调队列,先横着算一下每个长度为p的区间的最大值记录下来,然后再把记录下来的数组竖着同样算一下长度为q的区间,将每次求到的最大值取最小值。
 
ps:谨记像这种横着求一遍竖着求一遍的一定不能求第二遍的时候直接copy第一遍的代码改,会把自己坑死的!!!不要手懒!!!

代码

  1 #include<bits/stdc++.h>
2 #define ll long long
3 using namespace std;
4
5 const int maxn=1e6+10;
6 int nt1[maxn];
7 int nt2[maxn];
8 string s[maxn];
9 unordered_map<int,int> mp;
10 deque<int> dq;
11 int val[maxn],v[maxn];
12
13 void getnt1(string s)
14 {
15 int i=0,j=-1;
16 nt1[0]=-1;
17 while(i<s.size()){
18 if(j==-1||s[i]==s[j]) i++,j++,nt1[i]=j;
19 else j=nt1[j];
20 }
21 }
22
23 void getnt2(string s)
24 {
25 int i=0,j=-1;
26 nt2[0]=-1;
27 while(i<s.size()){
28 if(j==-1||s[i]==s[j]) i++,j++,nt2[i]=j;
29 else j=nt2[j];
30 }
31 }
32
33 int main()
34 {
35 ios::sync_with_stdio(false);
36 cin.tie(0);
37 cout.tie(0);
38
39 int n,m;
40 cin>>n>>m;
41 for(int i=0;i<n;i++) cin>>s[i];
42 for(int i=0;i<n;i++){
43 for(int j=0;j<m;j++){
44 cin>>v[i*m+j];
45 }
46 }
47
48 int pp=m,qq=n;
49 for(int i=0;i<n;i++){
50 getnt1(s[i]);
51 int p=nt1[m];
52 while(p!=-1){
53 mp[m-p]++;
54 if(mp[m-p]==n) pp=min(pp,m-p);
55 p=nt1[p];
56 }
57 }
58 mp.clear();
59 for(int i=0;i<m;i++){
60 string t;
61 for(int j=0;j<n;j++){
62 t+=s[j][i];
63 }
64 getnt2(t);
65 int p=nt2[n];
66 while(p!=-1){
67 mp[n-p]++;
68 if(mp[n-p]==m) qq=min(qq,n-p);
69 p=nt2[p];
70 }
71 }
72
73 int ans=1e9;
74 for(int i=0;i<n;i++){
75 while(dq.size()) dq.pop_back();
76 for(int j=0;j<pp-1;j++){
77 while(dq.size()&&v[i*m+dq.back()]<=v[i*m+j]) dq.pop_back();
78 dq.push_back(j);
79 }
80 for(int j=pp-1;j<m;j++){
81 while(dq.size()&&dq.front()+pp<=j) dq.pop_front();
82 while(dq.size()&&v[i*m+dq.back()]<=v[i*m+j]) dq.pop_back();
83 dq.push_back(j);
84 val[i*m+j]=v[i*m+dq.front()];
85 }
86 }
87 for(int i=pp-1;i<m;i++){
88 while(dq.size()) dq.pop_back();
89 for(int j=0;j<qq-1;j++){
90 while(dq.size()&&val[dq.back()*m+i]<=val[j*m+i]) dq.pop_back();
91 dq.push_back(j);
92 }
93 for(int j=qq-1;j<n;j++){
94 while(dq.size()&&dq.front()+qq<=j) dq.pop_front();
95 while(dq.size()&&val[dq.back()*m+i]<=val[j*m+i]) dq.pop_back();
96 dq.push_back(j);
97 ans=min(ans,val[dq.front()*m+i]);
98 }
99 }
100 ll res=(ll)ans*(ll)(pp+1)*(ll)(qq+1);
101 cout<<res<<endl;
102 return 0;
103 }

牛客网暑期ACM多校训练营(第二场)carpet的更多相关文章

  1. 牛客网暑期ACM多校训练营 第九场

    HPrefix Sum study from : https://blog.csdn.net/mitsuha_/article/details/81774727 k较小.分离x和k. 另外的可能:求a ...

  2. 牛客网暑期ACM多校训练营(第四场):A Ternary String(欧拉降幂)

    链接:牛客网暑期ACM多校训练营(第四场):A Ternary String 题意:给出一段数列 s,只包含 0.1.2 三种数.每秒在每个 2 后面会插入一个 1 ,每个 1 后面会插入一个 0,之 ...

  3. 牛客网暑期ACM多校训练营(第五场):F - take

    链接:牛客网暑期ACM多校训练营(第五场):F - take 题意: Kanade有n个盒子,第i个盒子有p [i]概率有一个d [i]大小的钻石. 起初,Kanade有一颗0号钻石.她将从第1到第n ...

  4. 牛客网 暑期ACM多校训练营(第二场)A.run-动态规划 or 递推?

    牛客网暑期ACM多校训练营(第二场) 水博客. A.run 题意就是一个人一秒可以走1步或者跑K步,不能连续跑2秒,他从0开始移动,移动到[L,R]的某一点就可以结束.问一共有多少种移动的方式. 个人 ...

  5. 牛客网 暑期ACM多校训练营(第一场)A.Monotonic Matrix-矩阵转化为格子路径的非降路径计数,Lindström-Gessel-Viennot引理-组合数学

    牛客网暑期ACM多校训练营(第一场) A.Monotonic Matrix 这个题就是给你一个n*m的矩阵,往里面填{0,1,2}这三种数,要求是Ai,j⩽Ai+1,j,Ai,j⩽Ai,j+1 ,问你 ...

  6. 牛客网暑期ACM多校训练营(第三场)H Diff-prime Pairs (贡献)

    牛客网暑期ACM多校训练营(第三场)H Diff-prime Pairs (贡献) 链接:https://ac.nowcoder.com/acm/contest/141/H来源:牛客网 Eddy ha ...

  7. 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)

    2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...

  8. 牛客网暑期ACM多校训练营(第七场)Bit Compression

    链接:https://www.nowcoder.com/acm/contest/145/C 来源:牛客网 题目描述 A binary string s of length N = 2n is give ...

  9. 牛客网暑期ACM多校训练营(第一场) - J Different Integers(线段数组or莫队)

    链接:https://www.nowcoder.com/acm/contest/139/J来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...

  10. 牛客网暑期ACM多校训练营(第九场) A题 FWT

    链接:https://www.nowcoder.com/acm/contest/147/A来源:牛客网 Niuniu has recently learned how to use Gaussian ...

随机推荐

  1. 算法历练之路——入学考试(JAVA)

    入学考试 时间限制: 1Sec 内存限制: 128MB 提交: 42 解决: 18 题目描述辰辰是个天资聪颖的孩子,他的梦想是成为世界 上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断 ...

  2. COW技术重置虚拟机

    最近使用COW技术做虚拟机重置,结果成功了,特地来给大家分享一下这次的成果! 文章目录 一.COW技术是什么? 二.重置虚拟机步骤 总结 往期杂文 一.COW技术是什么? Copy On Write, ...

  3. LeetCode662 二叉树最大宽度

    给定一个二叉树,编写一个函数来获取这个树的最大宽度.树的宽度是所有层中的最大宽度.这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空. 每一层的宽度被定义为两个端点(该层 ...

  4. leetcode-222完全二叉树的节点个数

    题目 给出一个完全二叉树,求出该树的节点个数. 说明: 完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置. ...

  5. Python模块化编程与装饰器

    Python的模块化编程 我们首先以一个例子来介绍模块化编程的应用场景,有这样一个名为requirements.py的python3文件,其中两个函数的作用是分别以不同的顺序来打印一个字符串: # r ...

  6. 编译安装PHP - 7.3.16

    编译安装PHP - 7.3.16 1 ) 安装依赖包: yum install -y gcc gcc-c++ make zlib zlib-devel pcre pcre-devel libjpeg ...

  7. git revert 回退已经push的内容

    如题,在日常的开发过程中,可能有组员不小心一下子吧文件修改,需要进行回退 回退主要涉及到2种命令,一种是git reset 一种是 git revert git reset 会修改git log提交历 ...

  8. SQL Server解惑——查询条件IN中能否使用变量

    在SQL Server的查询条件中,能否在IN里面使用变量呢? 如果可以的话,有没有需要注意的地方或一些限制呢?在回答这个问题前,我们先来看看这个例子: IF EXISTS (SELECT 1 FRO ...

  9. 【Linux】1、命令行及命令参数

    命令行及命令参数 文章目录 命令行及命令参数 1.命令行提示符 2.命令和命令参数 简单的命令 date ls 命令参数 短参数(一个字母) 长参数(多个字母) 参数的值 其它参数 3.小结 4.参考 ...

  10. 【Web】HTML入门小结

    文章目录 HTML? HTML 初识元素/标签 HTML语义化标签 标题 段落 font HTMl链接 HTML图像 HTML列表 HTML div HTML 块级元素与行内元素 HTML常用带格式作 ...