博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
牛客暑假多校第二场 K carpet
阅读量:6882 次
发布时间:2019-06-27

本文共 2996 字,大约阅读时间需要 9 分钟。

题意:给你一个n*m的矩阵 ,每个位置都有一个字符并且都有一个值,现在需要找到一个p*q的子矩阵, 原来的矩阵可以由现在这个矩阵无限复制然后截取其中的一部分得到,并且要求 子矩阵里最大的值 * (p+1)*(q+1)的值最小。

题解:对于每一行处理出可能的循环节长度, 然后找到一个长度是所有行的循环节, 对于列同样处理。然后问题就变成了对n*m所有的p*q的子矩阵的找到最小的最大值。这个操作用单调队列维护。

代码:

1 #include
2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair
pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e6 + 100; 18 string s, ss; 19 int val[N]; 20 int nx[N]; 21 int n, m; 22 inline int id(int x, int y){ 23 return m * x + y; 24 } 25 int cnt[N]; 26 void get_nt(int u){ 27 nx[0] = -1; 28 int j = 0, k = -1; 29 while(j < m){ 30 if(k == -1 || s[id(u,j)] == s[id(u,k)]) nx[++j] = ++k; 31 else k = nx[k]; 32 } 33 int pos = m; 34 while(pos != -1){ 35 cnt[m-pos]++; 36 pos = nx[pos]; 37 } 38 } 39 void get_nt_(int u){ 40 nx[0] = -1; 41 int j = 0, k = -1; 42 while(j < n){ 43 if(k == -1 || s[id(j,u)] == s[id(k,u)]) nx[++j] = ++k; 44 else k = nx[k]; 45 } 46 int pos = n; 47 while(pos != -1){ 48 cnt[n-pos]++; 49 pos = nx[pos]; 50 } 51 } 52 int a[N]; 53 LL mx[N]; 54 int main(){ 55 scanf("%d%d", &n, &m); 56 for(int i = 1; i <= n; i++){ 57 cin >> ss; 58 s += ss; 59 } 60 for(int i = 0; i < n*m; i++) 61 scanf("%d", &val[i]); 62 int p = 1, q = 1; 63 memset(cnt, 0, sizeof(cnt)); 64 for(int i = 0; i < n; i++) get_nt(i); 65 for(int i = 1; i <= m; i++){ 66 if(cnt[i] == n) { 67 p = i; 68 break; 69 } 70 } 71 memset(cnt, 0, sizeof(cnt)); 72 for(int i = 0; i < m; i++) get_nt_(i); 73 for(int i = 1; i <= n; i++){ 74 if(cnt[i] == m) { 75 q = i; 76 break; 77 } 78 } 79 /// q*p 80 for(int i = 0; i < n; i++){ 81 int l = 0 , r = -1; 82 for(int j = 0; j < m; j++){ 83 while(r >= l && val[id(i,a[r])] <= val[id(i,j)]) r--; 84 a[++r] = j; 85 while(r >= l && a[l] <= j-p) l++; 86 mx[id(i,j)] = val[id(i,a[l])]; 87 } 88 } 89 LL ans = INF; 90 for(int j = p-1; j < m; j++){ 91 int l = 0 , r = -1; 92 for(int i = 0; i < n; i++){ 93 while(r >= l && mx[id(a[r],j)] <= mx[id(i,j)]) r--; 94 a[++r] = i; 95 while(r >= l && a[l] <= i-q) l++; 96 if(i >= q-1) ans = min(ans, mx[id(a[l],j)]); 97 } 98 } 99 printf("%lld\n",1ll*ans*(p+1)*(q+1));100 return 0;101 }
View Code

 

转载于:https://www.cnblogs.com/MingSD/p/9360604.html

你可能感兴趣的文章
JVM 内部原理(六)— Java 字节码基础之一
查看>>
[iOS Xcode8]上传AppStore 无法构建版本 没有➕号
查看>>
前端网络、JavaScript优化以及开发小技巧
查看>>
js-权威指南学习笔记3
查看>>
WebApi系列~基于RESTful标准的Web Api
查看>>
Android DiskLruCache完全解析,硬盘缓存的最佳方案
查看>>
原谅我————这是,我很喜欢的一个故事
查看>>
Data Structure Visualizations
查看>>
Struts2中表单与Action传递数据三种方式
查看>>
前端模块化开发应用——日历组件开发
查看>>
项目工程的包package与文件夹的关系
查看>>
用户空间实现线程 内核实现线程 线程的调度
查看>>
工厂模式(Factory)
查看>>
wmi 一些配置(参考)
查看>>
Oracle以系统管理员的方式登录失败
查看>>
iOS开发之Runtime常用示例总结
查看>>
【转】Android应用如何跳转到应用市场详情页面
查看>>
c++——派生类和基类转换(类型兼容性原则)
查看>>
js调试工具Console命令详解
查看>>
Cannot call sendError() after the response has been committed - baiyangliu
查看>>