Codeforces 1500D - Tiles for Bathroom(贪心+队列)
首先先讲一发我的 \(n^2q\log n\) 的做法,虽然没有付诸实现并且我也深知它常数巨大过不去,但是我还是决定讲一讲(大雾
考虑设 \(f(i,j)\) 表示以 \(i,j\) 为左上角,满足其中不同颜色个数 \(\le q\) 的子正方形中大小最大的那个的边长,那么显然求出 \(f(i,j)\) 后一遍后缀和即可求出答案。于是问题转化为如何求 \(f(i,j)\)。注意到一个显然的结论:\(f(i,j)\ge f(i,j-1)-1\),故考虑用类似双针的方法求解,我们对于每一行动态地维护一个 \(len\) 表示当前子正方形的边长,每次将 \(len\) 加 \(1\) 并检验当前子正方形是否可行,如果不可行那么将 \(len\) 减 \(1\) 并 break
,此时的 \(len\) 值就是我们要求的 \(f(i,j)\),并再将 \(len\) 减一并考虑下一个格子 \(f(i,j+1)\),不难发现 \(len\) 最多变化 \(\mathcal O(n)\) 次,因此我们下面需考虑当 \(len\) 增大或减小时不同颜色个数的变化。注意到每次 \(len\) 加 \(1\) 等价于以下两个操作:
- 将某行 \(x\) 上的 \(l,l+1,l+2,\cdots,r\) 格子加入当前图形
- 将某列 \(x\) 上的 \(l,l+1,l+2,\cdots,r\) 格子加入当前图形
将 \(len\) 减一也同理。考虑怎样处理这个加入某行/某列的格子的操作,注意到 \(q\) 最多只有 \(10\),因此如果新加入的格子中不同颜色个数 \(>10\) 就肯定不合法了,这部分我们就对行/列分别双针预处理一遍,即对于每一个格子 \((i,j)\) 找出最大的 \(r\) 满足 \((i,j),(i,j+1),\cdots,(i,r)\) 中不同颜色个数 \(\le q\),以及最大的 \(r\) 满足 \((i,j),(i+1,j),\cdots,(r,j)\) 中不同颜色个数 \(\le q\),这样即可判断新加入的格子中不同颜色个数是否 \(\le q\),否则我们暴力枚举新加入的格子中不同颜色更新桶即可,计算某个颜色在新加入的格子中出现次数可用二分。枚举新加入的格子中不同的颜色的过程就在之前双针的过程中,额外记录下当前遍历到的不同颜色有哪些即可。时间复杂度 \(n^2q\log n\),稳了(指 T 稳了)
接下来就是正解了,我们考虑对于每个格子 \((i,j)\) 求出以它为右下角,且不同颜色个数 \(\le q\) 的最大正方形的边长,考虑怎样暴力求之——我们考察每个在该点左上方出现的颜色,对于每一种颜色我们求出该颜色的点与 \((i,j)\) 切比雪夫距离的最小值 \(d\),显然如果子正方形要包含该颜色,那么该子正方形边长必须 \(\ge d+1\),因此我们找出第 \(q+1\) 大的 \(d\),显然子正方形边长必须 \(<d\),否则子正方形中至少有 \(q+1\) 种颜色,而如果 \(d-1\le\min(i,j)\),一定存在一个以 \((i,j)\) 为右下角的边长为 \(d-1\) 的正方形,答案就是 \(d-1\),否则答案为 \(\min(i,j)\)。
考虑如何求 \(q+1\) 大的 \(d\),对于每一个点我们建立三个长度 \(q+1\) 的数组 \(L_{i,j},U_{i,j},LU_{i,j}\) 分别表示 \((i,j)\) 左方、上方、左上方出现过的、距离 \((i,j)\) 前 \(q+1\) 大的颜色,按照它们对应的 \(d\) 值从小到大排序。\(L_{i,j}\) 的求法是容易的,直接从 \(L_{i,j-1}\) 加一个点继承过来即可,\(U_{i,j}\) 也同理。至于 \(LU_{i,j}\),不难发现在 \(LU_{i,j}\) 出现过的颜色,必然在 \(L_{i,j},U_{i-1,j},LU_{i-1,j-1}\) 中至少一者出现过,因此我们把这三个数组看作一个队列,每次取出队首最小的元素即可在 \(\mathcal O(q)\) 时间内求出这三个数组。
时间复杂度 \(n^2q\)。
正解题解长度小于歪解是啥操作
const int MAXN=1500;
int n,c,a[MAXN+5][MAXN+5],cnt[MAXN+5],vis[MAXN*MAXN+5];
struct dat{
short int x,y;
dat(short int _x=0,short int _y=0):x(_x),y(_y){}
int col(){return a[x][y];}
};
int getdis(int x1,int y1,int x2,int y2){return max(x1-x2,y1-y2);}
dat L[MAXN+5][MAXN+5][12],U[MAXN+5][MAXN+5][12],LU[MAXN+5][MAXN+5][12];
int sL[MAXN+5][MAXN+5],sU[MAXN+5][MAXN+5],sLU[MAXN+5][MAXN+5];
int main(){
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
L[i][j][++sL[i][j]]=dat(i,j);
for(int k=1;k<=sL[i][j-1];k++){
if(L[i][j-1][k].col()==a[i][j]) continue;
if(sL[i][j]<=c) L[i][j][++sL[i][j]]=L[i][j-1][k];
}
U[i][j][++sU[i][j]]=dat(i,j);
for(int k=1;k<=sU[i-1][j];k++){
if(U[i-1][j][k].col()==a[i][j]) continue;
if(sU[i][j]<=c) U[i][j][++sU[i][j]]=U[i-1][j][k];
}
for(int p1=1,p2=1,p3=1;(p1<=sL[i][j]||p2<=sU[i-1][j]||p3<=sLU[i-1][j-1])&&sLU[i][j]<=c;){
int mn1=INF,mn2=INF,mn3=INF;
while(p1<=sL[i][j]&&vis[L[i][j][p1].col()]) ++p1;
while(p2<=sU[i-1][j]&&vis[U[i-1][j][p2].col()]) ++p2;
while(p3<=sLU[i-1][j-1]&&vis[LU[i-1][j-1][p3].col()]) ++p3;
if(p1<=sL[i][j]) mn1=getdis(i,j,L[i][j][p1].x,L[i][j][p1].y);
if(p2<=sU[i-1][j]) mn2=getdis(i,j,U[i-1][j][p2].x,U[i-1][j][p2].y);
if(p3<=sLU[i-1][j-1]) mn3=getdis(i,j,LU[i-1][j-1][p3].x,LU[i-1][j-1][p3].y);
int mn=min(mn1,min(mn2,mn3));
if(mn==INF) break;
if(mn==mn1) LU[i][j][++sLU[i][j]]=L[i][j][p1],vis[L[i][j][p1++].col()]=1;
else if(mn==mn2) LU[i][j][++sLU[i][j]]=U[i-1][j][p2],vis[U[i-1][j][p2++].col()]=1;
else LU[i][j][++sLU[i][j]]=LU[i-1][j-1][p3],vis[LU[i-1][j-1][p3++].col()]=1;
}
for(int k=1;k<=sLU[i][j];k++) vis[LU[i][j][k].col()]=0;
}
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
int d=(sLU[i][j]==c+1)?getdis(i,j,LU[i][j][c+1].x,LU[i][j][c+1].y):INF;
chkmin(d,min(i,j));
// printf("%d %d %d\n",i,j,d);
cnt[d]++;
}
for(int i=n;i;i--) cnt[i]+=cnt[i+1];
for(int i=1;i<=n;i++) printf("%d\n",cnt[i]);
return 0;
}
Codeforces 1500D - Tiles for Bathroom(贪心+队列)的更多相关文章
- codeforces Gym 100338E Numbers (贪心,实现)
题目:http://codeforces.com/gym/100338/attachments 贪心,每次枚举10的i次幂,除k后取余数r在用k-r补在10的幂上作为候选答案. #include< ...
- [Codeforces 1214A]Optimal Currency Exchange(贪心)
[Codeforces 1214A]Optimal Currency Exchange(贪心) 题面 题面较长,略 分析 这个A题稍微有点思维难度,比赛的时候被孙了一下 贪心的思路是,我们换面值越小的 ...
- CodeForces 797C Minimal string:贪心+模拟
题目链接:http://codeforces.com/problemset/problem/797/C 题意: 给你一个非空字符串s,空字符串t和u.有两种操作:(1)把s的首字符取出并添加到t的末尾 ...
- codeforces 349B Color the Fence 贪心,思维
1.codeforces 349B Color the Fence 2.链接:http://codeforces.com/problemset/problem/349/B 3.总结: 刷栅栏.1 ...
- [Swust OJ 352]--合并果子(贪心+队列模拟)
题目链接:http://acm.swust.edu.cn/problem/352/ Time limit(ms): 1000 Memory limit(kb): 65535 Description ...
- Codeforces Gym 100269E Energy Tycoon 贪心
题目链接:http://codeforces.com/gym/100269/attachments 题意: 有长度为n个格子,你有两种操作,1是放一个长度为1的东西上去,2是放一个长度为2的东西上去 ...
- codeforces 803D Magazine Ad(二分+贪心)
Magazine Ad 题目链接:http://codeforces.com/contest/803/problem/D ——每天在线,欢迎留言谈论. 题目大意: 给你一个数字k,和一行字符 例: g ...
- Codeforces 980E The Number Games 贪心 倍增表
原文链接https://www.cnblogs.com/zhouzhendong/p/9074226.html 题目传送门 - Codeforces 980E 题意 $\rm Codeforces$ ...
- Codeforces 798D Mike and distribution - 贪心
Mike has always been thinking about the harshness of social inequality. He's so obsessed with it tha ...
随机推荐
- JBOSS未授权访问漏洞利用
1. 环境搭建 https://www.cnblogs.com/chengNo1/p/14297387.html 搭建好vulhub平台后 进入对应漏洞目录 cd vulhub/jboss/CVE-2 ...
- 北航OO第三单元总结
JML基础梳理及工具链 JML的全称是Java Modeling language,即Java建模语言.JML是一种行为接口规格.它为严格的程序设计提供了一套行之有效的方法.通过JML不仅可以基于规格 ...
- Noip模拟44 2021.8.19
比较惊人的排行榜 更不用说爆零的人数了,为什么联赛会这么难!!害怕了 还要再努力鸭 T1 Emotional Flutter 考场上没切掉的神仙题 考率如何贪心,我们把黑色的条延长$s$,白色的缩短$ ...
- python基础语法--字典的遍历
原文链接:https://blog.csdn.net/normang/article/details/55804231 (1)遍历key值 >>> a {'a': '1', 'b': ...
- 快速了解XML
1. XML 定义 可扩展标记语言,标准通用标记语言的子集,简称XML.是一种用于标记电子文件使其具有结构性的标记语言. 2. XML 展示 如下是一个xml的标记展示,XML 是不作为的XML 被设 ...
- Android编译执行envsetup.sh,产生工具命令m、mm、mmm、mmma、tapas 、croot、cgrep、jgrep、 resgrep、godir
一般来说编译一个sdk或者一个比较大的工程项目,第一步都是执行 envsetup.sh这个脚本,比如编译android,qt源码以及其他一些嵌入式的sdk. 而且执行的时候需要特别注意使用 sourc ...
- dhcpd:bad subnet number/mask combination. subnet
今天在调试wifi热点启动hdcpd服务时出现报错"bad subnet number/mask combination. subnet 192.168.1.1", Interne ...
- POJ 2536 Gopher II(二分图最大匹配)
题意: N只地鼠M个洞,每只地鼠.每个洞都有一个坐标. 每只地鼠速度一样,对于每只地鼠而言,如果它跑到某一个洞的所花的时间小于等于S,它才不会被老鹰吃掉. 规定每个洞最多只能藏一只地鼠. 问最少有多少 ...
- 力扣 - 剑指 Offer 66. 构建乘积数组
题目 剑指 Offer 66. 构建乘积数组 思路1 按照一般的思路就是将所有的相乘,然后除以每一位数字就是答案,但是题目要求我们不能使用除法,因此我们会想到每次遍历到每个数字的时候,在遍历一遍数组, ...
- #ifndef #define #endif #ifdef 避免重复引用
一:在什么阶段处理 ? 预处理 预处理 预处理 首先注意这四个头文件保护符是在预处理阶段由系统默认的预处理器(Linux操作系统上默认是cpp)来处理的.它们的含义如下: #define XXX // ...