题目大意:给你一个n*n的矩阵,现在问对于每个k\le n,求出所有k*k的子矩阵中,元素种类数不超过q的矩阵个数,n\le 1500, q\le 10

先考虑最暴力的做法:

对于每个格子,求出以它为子矩阵右下角时,左上角能到达的最远位置,时间O(n^{4})。再统计起来跑个后缀和

考虑可以$n^{3}$时的做法:

双指针对一条斜线上的格子进行维护,暴力进行指针移动时的更新

虽然双指针是一种优化递推,但其并没有利用q=10的性质

考虑直接递推

我们从左到右再从上到下依次处理每个点

对于每个格子维护一个vector,记录从它开始,不断向左上拓展时,第一次出现某个元素的相对位置信息

比如

1 2 3 ...

1 5 3 ...

1 2 3 ...

...

现在要处理(3,3)位置上的那个3

那么它相对于(3,3)的位置就是(3,3),中间的5相对位置是(2,2)。

5下面的2相对位置也是(2,2),因为如果想在(3,3)把这个2框进去,左上角一定会拓展到(2,2)

5上面的2相对位置是(1,1),但可惜在记录的时候我们只记录第一次出现的位置

我们最多只需要记录q+1个元素,第q+1个元素往右下一格就是答案

当前格子左,上,左上的三个相邻格子都是已知信息,取出来排序,再依次选第一次出现的位置

但左和上取出来时相对位置可能会改变

画图发现,这与元素在倒L形的左侧一列/上侧一行的出现情况有关,额外记录元素在这个倒L形左列/上行的出现情况,再进行大讨论即可转移

直接做会被卡空间,滚动数组就好

  1 int T,n,q;
2 int a[N1][N1],sum[N1][N1];
3 struct node{
4 int x,y,val; bool tp,le;
5 };
6 int cmp(node &s1,node &s2)
7 {
8 return s1.x+s1.y>s2.x+s2.y;
9 }
10
11 int ans[N1];
12 int now,pst;
13 vector<node>to[N1][N1];
14 node se[50];
15 int tot;
16
17 void addnode(int x,int y,int nx,int ny)
18 {
19 int m; node k;
20 if(x==nx-1&&y==ny-1)
21 {
22 m=to[pst][y].size();
23 for(int i=0;i<m;i++)
24 {
25 k=to[pst][y][i]; se[tot++]=k;
26 // se[tot++]=(node){k.x,k.y,k.val,k.tp.k.le};
27 }
28 }
29 if(x==nx-1&&y==ny)
30 {
31 m=to[pst][y].size();
32 for(int i=0;i<m;i++)
33 {
34 k=to[pst][y][i];
35 if(x==k.x&&y==k.y){
36 if(y>1) k.y--; else continue;
37 k.le=0; k.tp=1;
38 }else if(!k.tp){
39 k.x++; k.tp=(a[k.x][k.y]==k.val)?1:0; k.le=1;
40 }else{
41 if(k.y>1) k.y--; else continue; // 后续与左侧取并!!
42 k.le=(a[k.x][k.y]==k.val)?1:0;
43 }
44 se[tot++]=k;
45 }
46 }
47 if(x==nx&&y==ny-1)
48 {
49 m=to[now][y].size();
50 for(int i=0;i<m;i++)
51 {
52 k=to[now][y][i];
53 if(x==k.x&&y==k.y){
54 k.x--;
55 k.le=1; k.tp=0;
56 }else if(!k.le){
57 k.y++; k.le=(a[k.x][k.y]==k.val)?1:0; k.tp=1;
58 }else{
59 if(k.x>1) k.x--; else continue; // 后续与上侧取并!!
60 k.tp=(a[k.x][k.y]==k.val)?1:0;
61 }
62 se[tot++]=k;
63 }
64 }
65 }
66 void solve(int x,int y)
67 {
68 tot=0; se[tot++]=(node){x,y,a[x][y],1,1};
69 addnode(x-1,y,x,y);
70 if(y>1) addnode(x-1,y-1,x,y), addnode(x,y-1,x,y);
71 sort(se,se+tot,cmp); node k; int fl;
72 for(int i=0;i<tot;i++)
73 {
74 k=se[i]; fl=0;
75 for(int j=0;j<to[now][y].size();j++)
76 {
77 if(to[now][y][j].val==k.val)
78 {
79 if(to[now][y][j].x==k.x && to[now][y][j].y==k.y)
80 to[now][y][j].tp|=k.tp, to[now][y][j].le|=k.le;
81 fl=1; break;
82 }
83 }
84 if(!fl)
85 {
86 to[now][y].push_back(k);
87 if(to[now][y].size()==q+1) break;
88 }
89 }
90 int m=to[now][y].size();
91 // sum[x][y]=x-to[now][y][m-1].x+1;
92 if(m==q+1) sum[x][y]=x-to[now][y][m-1].x;
93 else sum[x][y]=min(x,y);
94 }
95
96 int ret[N1];
97 int main()
98 {
99 // freopen("a.txt","r",stdin);
100 freopen("a.in","r",stdin);
101 // srand(time(NULL));
102 scanf("%d%d",&n,&q);
103 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) read(a[i][j]);
104 now=1, pst=0;
105 for(int j=1;j<=n;j++)
106 {
107 to[0][j].push_back( (node){1,j,a[1][j],1,1} );
108 sum[1][j]=1;
109 }
110 for(int i=2;i<=n;i++)
111 {
112 for(int j=1;j<=n;j++)
113 {
114 to[now][j].clear();
115 solve(i,j);
116 }
117 swap(now,pst);
118 }
119 for(int i=1;i<=n;i++)
120 {
121 for(int j=1;j<=n;j++)
122 {
123 ret[1]++; ret[sum[i][j]+1]--;
124 // printf("%d ",sum[i][j]);
125 }
126 // puts("");
127 }
128 for(int i=1;i<=n;i++) ret[i]=ret[i-1]+ret[i];
129 for(int i=1;i<=n;i++) printf("%d\n",ret[i]);
130 return 0;
131 }

CF1500D Tiles for Bathroom (递推+大讨论)的更多相关文章

  1. POJ 2506 Tiling(递推+大整数加法)

    http://poj.org/problem?id=2506 题意: 思路:递推.a[i]=a[i-1]+2*a[i-2]. 计算的时候是大整数加法.错了好久,忘记考虑1了...晕倒. #includ ...

  2. (递推 大整数) Children’s Queue hdu1297

    Children’s Queue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. LightOJ 1244 - Tiles 猜递推+矩阵快速幂

    http://www.lightoj.com/volume_showproblem.php?problem=1244 题意:给出六种积木,不能旋转,翻转,问填充2XN的格子有几种方法.\(N < ...

  4. java算法面试题:递归算法题2 第1个人10,第2个比第1个人大2岁,依次递推,请用递归方式计算出第8个人多大?

    package com.swift; public class Digui_Return { public static void main(String[] args) { /* * 递归算法题2 ...

  5. P1067Warcraft III 守望者的烦恼(十大矩阵问题之七求递推式)

    https://vijos.org/p/1067 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她 ...

  6. 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】

    还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...

  7. HDU1297 Children’s Queue (高精度+递推)

    Children’s Queue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. Permutation Descent Counts(递推)

    1968: Permutation Descent Counts Submit Page   Summary   Time Limit: 1 Sec     Memory Limit: 128 Mb  ...

  9. Hanoi双塔问题(递推)

    Hanoi双塔问题 时间限制: 1 Sec  内存限制: 128 MB提交: 10  解决: 4[提交][状态][讨论版][命题人:外部导入] 题目描述 给定A,B,C三根足够长的细柱,在A柱上放有2 ...

随机推荐

  1. [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (5) 嵌入式hash表

    [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (5) 嵌入式hash表 目录 [源码解析] NVIDIA HugeCTR,GPU版本参数服务器--- (5) 嵌入式hash表 ...

  2. 了解MySQL存储引擎工作原理

    MySql数据库最大的特色就是其插件式的存储引擎架构,本文主要介绍MySql常用的存储引擎,为开发时选择合适的存储引擎提供参考. 1. MySql体系结构# 在介绍存储引擎之前先来介绍下MySql的体 ...

  3. elk监听Java日志发送微信报警

    一年前写过logstash根据日志关键词报警 ,今年重温一下.并且记录一下遇到的问题解决办法. Java错误日志一般出现一大坨,如下图: 所以我们的filebeat日志收集器就要改成多行匹配模式,以日 ...

  4. 前端点击png透明部分解决方案

    看效果:点击空白区域红色1.点击实体区域红色2.分别得到颜色数据(包括透明度数据),控制台蓝色1.2.根据颜色数据即可解决png透明部分的点击问题. 让图片不能点击,分两种 1. 整张图片不能点击.这 ...

  5. java-23种设计模式概述【软件设计模式基本介绍(是什么、作用、优点)、模式的分类和介绍】

    一.设计模式基本介绍(是什么.作用.优点) 1.软件设计模式是什么? 软件设计模式(Software Design Pattern),又称设计模式. 2.设计模式的作用 ★ 提高代码的可复用性.可维护 ...

  6. 分析CC攻击以及防御

    实验目的 了解DDoS攻击原理,及一个DDoS攻击的过程 实验内容 了解DDoS攻击原理,及一个DDoS攻击的过程 实验环境描述 1. 学生机与实验室网络直连: 2. VPC1与实验室网络直连: 3. ...

  7. C# 属性(一)

    C# 中的属性是特殊的方法,该方法只负责对私有字段经行的操作,.我们用反编译查看时候看到真实属性是带()的方法,里面还包含get()和set()方法. 属性完成对私有字段的封装.对类的外部用户来说,属 ...

  8. 判断访问类型是pc端还是移动端

    /**      * 判断访问类型是电脑还是手机      */     $(function(){         var mobile_flag = isMobile(); // true为PC端 ...

  9. P4-可编程语言代码学习

    (1).behavioral-model 简称bmv2 P4程序首先经过p4c-bm模块编译成JSON格式的配置文件,然后将配置文件载入到bmv2中,转化成能实现交换机功能的数据结构. behavio ...

  10. package.xml使用说明

    1. package.xml使用说明 a. pacakge.xml 包含了package的名称. 版本号. 内容描述. 维护人员. 软件许可. 编译构建工具. 编译依赖. 运行依赖等信息. 2. pa ...