传送门: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. SpringBoot入门 简单搭建和使用

    前言 差不多两年前,那个时候我准备要做毕业设计了,才第一次知道java有框架这种东西,在网上找了好多SSM的教程,那会儿真的是Spring+SpringMVC+MyBatis搭建的,印象极深的是还要写 ...

  2. 基于JavaFX实现的音乐播放器

    前言 这个是本科四年的毕业设计,我个人自命题的一个音乐播放器的设计与实现,其实也存在一些功能还没完全开发完成,但粗略的答辩也就过去了,还让我拿了个优秀,好开心.界面UI是参考网易云UWP版本的,即使这 ...

  3. 使用Jenkins+Blue Ocean 持构建自动化部署之安卓源码打包、测试、邮件通知

    什么是BlueOcean? BlueOcean重新考虑了Jenkins的用户体验.BlueOcean由Jenkins Pipeline设计,但仍然兼容自由式工作,减少了团队成员的混乱,增加了清晰度. ...

  4. CTFshow-萌新赛杂项_签到

    查看网页信息 http://game.ctf.show/r2/ 把网页源码下载后发现有大片空白 使用winhex打开 把这些16进制数值复制到文件中 把20替换为0,09替换为1后 得到一串二进制数值 ...

  5. 三十二:WEB漏洞-文件操作之文件下载读取全解

    文件下载读取 原路,检测,利用,修复 利用 数据库配置文件下载或者读取后续 接口密钥信息文件下载或者读取后续 文件名,参数值,目录符号 read.xxx?filename= down.xxx?file ...

  6. python的零碎知识

    1.Python代码操作git 安装 pip3 install gitpython 操作git import os from git.repo import Repo # gitpython def ...

  7. Linux定时任务crontab通俗易懂简单扼要地解析

    1.安装crontab 在配置好yum源的情况下,直接执行如下命令即可: yum install crontab 2.查看当前环境上已经有的定时任务有哪些? 执行如下命令即可 crontab -l 如 ...

  8. UDP flood UDP Port Denial-of-Service Attack

    https://baike.baidu.com/item/UDP%20flood/5504851 UDPFlood是日渐猖厥的流量型DoS攻击,原理也很简单.常见的情况是利用大量UDP小包冲击DNS服 ...

  9. openrstry 限流 是否有清零逻辑 连接池

    openrstry  限流  是否有清零逻辑 https://github.com/openresty/lua-resty-limit-traffic # encoding=utf-8 # Shawn ...

  10. Springboot中mybatis控制台打印sql语句

    Springboot中mybatis控制台打印sql语句 https://www.jianshu.com/p/3cfe5f6e9174 https://www.jianshu.com/go-wild? ...