题目:戳这里

题意:给一个n*m的矩阵,里面由a~z及A~Z构成,问有多少个子矩阵满足任意一行或一列中都没有相同的字母。

解题思路:左上角和右下角两点可以确定一个矩阵。可以先预处理出来每个点作为一个矩阵的右下角,向左和向上的最长值。然后遍历每个点是右下角的情况,计算该点为右下角时,能构成多少个矩阵。计算方法为:

1.设右下角为(i,j),它向左的最长值为r[i][j],向上最长之为c[i][j],设左上角为(x,y)。

2.遍历j~j-r[i][j]+1,维护最小值minn[]。

3.根据minn[]数组和c[][]数组,找到符合条件的左上角,计入答案。

这三步操作的原因是,一个符合条件的左上角(x,y),要满足矩形底边上所有点的i-c[i][k]+1>=x,右边上所有点的j-r[k][j]+1>=y。

代码思路比较绕,写的时候得静下心。

附ac代码:

 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <string>
6 #include <cmath>
7 #include <map>
8
9 using namespace std;
10 typedef long long ll;
11 const int maxn = 1e3 + 10;
12 char st[maxn][maxn];
13 int r[maxn][maxn], c[maxn][maxn];
14 int pos[maxn];
15 int minn[maxn];
16 const int inf = 0x3f3f3f3f;
17 int main()
18 {
19 int n, m;
20 scanf("%d %d", &n, &m);
21 for(int i = 1; i <= n; ++i)
22 {
23 scanf("%s", st[i] + 1);
24 }
25 int len = 0;
26 int cnt = 0;
27 for(int i = 1; i <= n; ++i)
28 {
29 memset(pos, 0, sizeof(pos));
30 for(int j = 1; j <= m; ++j)
31 {
32 len = st[i][j] - 'A';
33 r[i][j] = j - pos[len];
34 r[i][j] = min(r[i][j], r[i][j - 1] + 1);//避免abba时,无法更新pos
35 pos[len] = j;
36 }
37 }
38 for(int j = 1; j <= m; ++j)
39 {
40 memset(pos, 0, sizeof(pos));
41 for(int i = 1; i <= n; ++i)
42 {
43 len = st[i][j] - 'A';
44 c[i][j] = i - pos[len];
45 c[i][j] = min(c[i][j], c[i - 1][j] + 1);//同上
46 pos[len] = i;
47 }
48 }
49 ll ans = 0;
50 for(int i = 1; i <= n; ++i)
51 {
52 memset(minn, inf, sizeof(minn));
53 for(int j = 1; j <= m; ++j)
54 {
55 for(int k = j; k >= j - r[i][j] + 1; --k)
56 minn[k] = min(minn[k + 1], c[i][k]);//(i,k)点能取到的最远列
57
58 int len = j - r[i][j] + 1;
59
60 for(int k = i; k >= i - c[i][j] + 1; --k)
61 {
62 while(minn[len] < i - k + 1 || r[k][j] < j - len + 1)//倘若点(i,j)的minn值取不到k或(k,j)本身取不到minn,则说明len不符合条件
63 {
64 ++ len;
65 if(len > j) break;
66 }
67 if(len > j) break;
68 ans += j - len + 1;
69 // printf("%lld ans\n", ans);
70 }
71 //printf("%d ans\n",ans);
72 }
73 }
74 printf("%lld\n", ans);
75 return 0;
76 }

最新文章

  1. XVI Open Cup named after E.V. Pankratiev. GP of Eurasia
  2. angularjs指令系统系列课程(2):优先级priority,模板template,模板页templateUrl
  3. Java 线程 — ConcurrentHashMap
  4. Cron表达式简单学习
  5. MySQL(四) —— 操作数据表中的记录
  6. ARM处理器模式
  7. networkRequest
  8. 网站优化指南之数据库缓存、CDN与云存储
  9. 手把手教popupWindow从下往上,以达到流行效果
  10. [COGS2701]:动态树
  11. DB Query Analyzer 6.01 is released, SQL Execute Schedule function can be used
  12. 说一说js中__proto__和prototype以及原型继承的那些事
  13. C#基于wpf编写的串口调试助手
  14. map的循环删除操作
  15. 利用java webservice调用天气预报实践
  16. @Transactional noRollbackFor
  17. Mac的brew和brew cask区别以及安装brew cask
  18. Vue - 起手式
  19. json过滤某些属性 之@jsonignore
  20. nova event

热门文章

  1. 力软最新版本与.netCore版本
  2. ichartjs插件的使用
  3. Typora+PicGo+Gitee打造图床
  4. 控制tomcat日志文件的输出到catalina.out
  5. 三分钟学会 ASP.NET Core WebApi使用Swagger生成api说明文档
  6. Vue3(三)CND + ES6的import + 工程化的目录结构 = 啥?
  7. Vagrant基本知识、基本操作
  8. 用友GRP-u8 SQL注入
  9. ubuntu 安装新版的qq,可支持下载文件等常用功能
  10. linux yum rpm 和 apt-get dpkg 安装、卸载软件