codeforces 407D Largest Submatrix 3
codeforces 407D Largest Submatrix 3
题意
找出最大子矩阵,须满足矩阵内的元素互不相等。
题解
官方做法
http://codeforces.com/blog/entry/11333
- \(O(n^6)\)
- 枚举子矩阵,暴力check。
- \(O(n^4)\)
- 枚举上下边界,双指针。
- \(O(n^3log_2n)\)
- 假设当前上边界 \(up\), 下边界 \(down\),\(R_i\) 表示当 \(i\) 为左边界时,右边界最大是 \(R_i\)。
- 当 \(down->down+1\) 时,\(R_i\) 要么不变,要么减小。
- 减小的情况:\(a_{down+1, j}(i<=j<=R_i)\) 在矩阵 \((up, i, down, R_i)\) 中出现。
- 因此对于每个 \(a_{down+1, j}(i<=j<=R_i)\),我们需要寻找在矩阵 \((up, i, down, R_i)\) 中出现的,从左边最靠近 \(j\),和从右边最靠近 \(j\) 的两个位置。这个可以用set维护。
- \(O(n^3)\)
- 如何优化掉 \(O(n^3log_2n)\) 做法的 \(log_2n\) ?
- 从大到小枚举 \(up\)。当 \(up->up-1\) 时,\(O(n^2)\) 更新 \((up, 1, n, m)\) 中所有点的从左边最靠近,和从右边最靠近的两个位置。
区间dp做法
\(f_{i, l, r}\)表示下边界是 \(i\), 左右边界是 \(l, r\) 时,上边界的值。
\(f_{i, l, r}=max\{f_{i-1, l, r}, f_{i, l+1, r}, f_{i, l, r-1}, a_{i, l}与a_{1-i, r}的限制, a_{i, r}与a_{1-i, l}的限制\}\)

可以这样理解:\(f_{i, l, r}\) 需要维护A、B、C、D、E、F这六个块之间的关系,\(f_{i-1, l, r}\) 只维护了A、B、C之间的关系,\(f_{i, l+1, r}\) 只维护了B、C、E、F之间的关系,\(f_{i, l, r-1}\) 只维护了A、B、D、E之间的关系,剩下的还需维护A与F、C与D、D与F的关系。
// 代码实现可以省掉第一维。
代码
\(O(n^3log_2n)\)做法
T了 不知道有没有写错
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(x) (int)x.size()
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int N=404;
int n,m;
int a[N][N], R[N], cnt[N*N];
set<int> pos[N*N];
int solve() {
int ans=1;
rep(up,1,n+1) {
rep(i,0,N*N) pos[i].clear();
rep(i,0,m+1) R[i]=m;
rep(down,up,n+1) {
int r=0;
rep(i,1,m+1) {
while(r<m&&!cnt[a[down][r+1]]) {
++r;
++cnt[a[down][r]];
}
R[i]=min(R[i], r);
--cnt[a[down][i]];
}
rep(j,1,m+1) {
int c=a[down][j];
auto it1=pos[c].upper_bound(j);
auto it2=pos[c].lower_bound(j);
if(it1!=pos[c].begin()) {
--it1;
if(*it1<=j) R[*it1]=min(R[*it1], j-1);
}
if(it2!=pos[c].end()) {
if(j<=*it2) R[j]=min(R[j], *it2-1);
}
}
for(int i=m-1;i;--i) R[i]=min(R[i], R[i+1]);
rep(i,1,m+1) if(i<=R[i]) ans=max(ans, (down-up+1)*(R[i]-i+1));
rep(i,1,m+1) pos[a[down][i]].insert(i);
}
}
return ans;
}
int main() {
while(~scanf("%d%d",&n,&m)) {
///read
rep(i,1,n+1) rep(j,1,m+1) scanf("%d",&a[i][j]);
///solve
printf("%d\n",solve());
}
return 0;
}
\(O(n^3)\) 做法
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(x) (int)x.size()
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int N=404;
int n, m;
int a[N][N], p[N*N], l[N][N], r[N][N], R[N];
void Min(int &a, int b) {
if(a>b) a=b;
}
void Max(int &a, int b) {
if(a<b) a=b;
}
int solve() {
int ans=1;
rep(i,0,n+1) rep(j,0,m+1) l[i][j]=0, r[i][j]=m+1;
for(int u=n;u;--u) {
rep(i,1,m+1) p[a[u][i]]=0;
rep(i,1,m+1) l[u][i]=p[a[u][i]], p[a[u][i]]=i;
rep(i,1,m+1) p[a[u][i]]=m+1;
for(int i=m;i;--i) r[u][i]=p[a[u][i]], p[a[u][i]]=i;
memset(p,0,sizeof(p));
rep(i,1,m+1) {
p[a[u][i]]=i;
rep(v,u+1,n+1) Max(l[v][i], p[a[v][i]]);
}
rep(i,0,N*N) p[i]=m+1;
for(int i=m;i;--i) {
p[a[u][i]]=i;
rep(v,u+1,n+1) Min(r[v][i], p[a[v][i]]);
}
rep(i,1,m+1) R[i]=m+1;
rep(v,u,n+1) {
rep(i,1,m+1) {
Min(R[l[v][i]], i);
Min(R[i], r[v][i]);
}
for(int i=m-1;i;--i) Min(R[i], R[i+1]);
rep(i,1,m+1) {
Max(ans, (v-u+1)*(R[i]-i));
}
}
}
return ans;
}
int main() {
while(~scanf("%d%d",&n,&m)) {
///read
rep(i,1,n+1) rep(j,1,m+1) scanf("%d",&a[i][j]);
///solve
printf("%d\n",solve());
}
return 0;
}
区间dp做法
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(x) (int)x.size()
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int N=404;
int n,m;
int a[N][N], f[N][N], p[N][160004];
int main() {
while(~scanf("%d%d",&n,&m)) {
rep(i,1,n+1) rep(j,1,m+1) scanf("%d",&a[i][j]);
memset(f,0,sizeof(f));
memset(p,0,sizeof(p));
int ans=1;
rep(i,1,n+1) {
rep(len,1,m+1) {
for(int l=1, r=len;r<=m;++l, ++r) {
if(l==r) {
f[l][r]=max(f[l][r], p[l][a[i][l]]);
} else {
f[l][r]=max(f[l][r], max(f[l][r-1], f[l+1][r]));
f[l][r]=max(f[l][r], max(p[l][a[i][r]], p[r][a[i][l]]));
if(a[i][l]==a[i][r]) f[l][r]=i;
}
ans=max(ans, (i-f[l][r])*(r-l+1));
}
}
rep(j,1,m+1) p[j][a[i][j]]=i;
}
printf("%d\n",ans);
}
return 0;
}
codeforces 407D Largest Submatrix 3的更多相关文章
- Largest Submatrix(动态规划)
Largest Submatrix Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- POJ-3494 Largest Submatrix of All 1’s (单调栈)
Largest Submatrix of All 1’s Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 8551 Ac ...
- hdu 2870 Largest Submatrix(平面直方图的最大面积 变形)
Problem Description Now here is a matrix with letter 'a','b','c','w','x','y','z' and you can change ...
- Largest Submatrix of All 1’s
Given a m-by-n (0,1)-matrix, of all its submatrices of all 1’s which is the largest? By largest we m ...
- Largest Submatrix of All 1’s(思维+单调栈)
Given a m-by-n (0,1)-matrix, of all its submatrices of all 1's which is the largest? By largest we m ...
- POJ 3494 Largest Submatrix of All 1’s 单调队列||单调栈
POJ 3494 Largest Submatrix of All 1’s Description Given a m-by-n (0,1)-matrix, of all its submatrice ...
- POJ - 3494 Largest Submatrix of All 1’s 单调栈求最大子矩阵
Largest Submatrix of All 1’s Given a m-by-n (0,1)-matrix, of all its submatrices of all 1’s which is ...
- HDU 2870 Largest Submatrix (单调栈)
http://acm.hdu.edu.cn/showproblem.php? pid=2870 Largest Submatrix Time Limit: 2000/1000 MS (Java/Oth ...
- MINSUB - Largest Submatrix
MINSUB - Largest Submatrix no tags You are given an matrix M (consisting of nonnegative integers) a ...
随机推荐
- 13 Timer和TimerTask
下面内容转载自:http://blog.csdn.net/xieyuooo/article/details/8607220 其实就Timer来讲就是一个调度器,而TimerTask呢只是一个实现了ru ...
- Linux笔记-Linux的命令初解1
我是一个Linux的初学者,经验肯定没有大牛们那么全面,但是我很想把自己在学习过程中的所有所学和一些自己的感悟写下来. 首先我主要看的书为<鸟哥的私房菜>,这是一本非常棒的书,但是你会发现 ...
- JAVA 方法 和Scanner
方法:包含于类或对象中,是解决一类问题步骤的有序组合. 算法:解决一类问题的思想. Scanner next()与nextLine()区别 next(): 1.一定要读取到有效字符后才可以结束输入. ...
- [java] byte不能直接相加
以下赋值语句将产生一个编译错误,原因是赋值运算符右侧的算术表达式在默认情况下的计算结果为 int 类型. // Error: conversion from int to byte:byte z = ...
- 【转】Java面试题全集(上)
准备从C#转java,在找工作之前准备看看面试题,有幸看到大神的作品,mark一下,以后慢慢看... 2013年年底的时候,我看到了网上流传的一个叫做<Java面试题大全>的东西,认真的阅 ...
- excel 工作表如何插入当前日期时间
在EXCEL表格中,插入当前的日期或是插入当前的时间:我们都可以用快捷键或时间函数来实现 插入当前日期 快捷键方法: 比如,显示日期的单元格为A1单元格: 今天是2018年6月8日: 鼠标点一下A1单 ...
- 使用IndexOf方法来判断“咳嗽”出现的次数及索引、使用Dictionary<key,value> 集合统计没个字符出现的次数
static void Main(string[] args) { #region string str = "患者:医生我咳嗽的很严重,大夫:你多大年纪了? 患者:我75岁 大夫:那二十岁 ...
- Xss和Csrf介绍
Xss和Csrf介绍 Xss Xss(跨站脚本攻击),全称Cross Site Scripting,恶意攻击者向web页面中植入恶意js代码,当用户浏览到该页时,植入的代码被执行,达到恶意攻击用户的目 ...
- C#图片验证码绘制
制作验证码.也可以画弧线之类..... //新建一个网站,在后台代码中引用一个using Stystem.Drawing的命名空间 Bitmap img = , ); //制作一个宽100,高50的画 ...
- Oracle数据库的监控及数据维护
目前Oracle数据库的管理,数据查询等都需要安装Oracle软件或安装Oracle Client等,远程访问都需要先登录到服务器等繁琐的操作.如果是开发团队,那么每个开发,测试,管理人员都要经历这个 ...