(全英文题面所以直接放化简题意)

题意:在一个二维平面内,初始有一些点,然后每个时间点加入一些点,对每个时间点求平面内最大的无障碍正方形

(这次的题目是真的神仙啊。。。)

  • 首先,考虑暴力,如果对每一个加点进行一遍扫描,那么,可以跑到天荒地老了。。。
  • 其次,如果像以前的dp一样跑呢?因为是动态的,所以不行。。。
  • 很容易想到,这个面积一定是单调不增的,于是,就可以倒序来,变成加点,离线做。
  • 那么,有了加点就可以跑暴力了吗?很显然不行。。。
  • 那怎么办呢?

solution:

(以下初始思路来自老师)

这个正方形可能出现在哪里?

  1. 一个点左上
  2. 左下
  3. 右上
  4. 右下

一个正方形由长和宽构成,要找最大边长,其实就是要维护两个东西:长和宽。

分别考虑长宽如何维护(好吧差不多都是边长)

宽:它可能经过一个点,也就是这个点在宽这条边上。

于是不太容易想到:维护两个dp数组,存每个点向左右能拓展的长度。

但是,如果依旧暴力更新,还是会炸成渣滓。。。

瞪大眼看题,当一个点更新时,只有它所在的一行会变,所以就可以O(n)更新dp数组了。

于是,只要在每个点加上后更新dp数组,然后查出最大正方形,就完事了

下面考虑列:

能不能像刚刚那样继续dp嘞?(像cdq那样dp套dp呢???)如果这样做,那可能会得到一个错位的正方形。。。很麻烦.....

况且我们要去最大的不是吗?这好像有什么提示.....

想想我学过的维护最值的数据结构(qsort rmq 线段树 单调队列 主席树 平衡树 树套树)

再结合一下问题实际:找长度,不太容易想到,对于每一个答案,进行一次check。这个check,有点像二分,对于每一个可行答案进行判断然后更新最优解。而这个可行答案,就是看是否能找到更大的正方形。

对此,只需要枚举是否能找到比当前更大的边长就行了。因为它是正方形,所以长宽相等,这里列问题就转化为了:

对于每一个定长区间,找最大的一个之前处理出的dp数组里是否有一个长度大于等于它的值,也就是最大值。

这就很明朗了,线段树,单调队列。

两者差距在哪里呢?线段树O(nlogn)单调队列O(n);

我用了单调队列。

这份代码给我的感觉就是:代码还可以继续化简,逻辑运算符可以有效增加效率和增加美观度

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=;
char s[maxn];
int n,m,k;
int a[maxn][maxn];
struct node
{
int x,y,res;
}ans[maxn];
int f[maxn][maxn];
int l[maxn][maxn];
int r[maxn][maxn]; void init()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int j=;j<=m;j++)
{
a[i][j]=(s[j]=='.');
}
}
for(int i=;i<=k;i++)
{
scanf("%d%d",&ans[i].x,&ans[i].y);
a[ans[i].x][ans[i].y]=;
}
} void dp()
{
for(int i=;i<=n;i++)
{
for(int j=m;j>=;j--)
{
if(!a[i][j])
continue;
if(i==||j==m)
{
f[i][j]=;
ans[k].res=max(ans[k].res,);
continue;
}
f[i][j]=min(f[i-][j],f[i][j+]);
if(a[i-f[i][j]][j+f[i][j]])f[i][j]++;
ans[k].res=max(ans[k].res,f[i][j]);
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
l[i][j]=a[i][j]*(l[i][j-]+);
}
}
for(int i=;i<=n;i++)
{
for(int j=m;j>=;j--)
{
r[i][j]=a[i][j]*(r[i][j+]+);
}
}
} int tmp[maxn];
int q[maxn]; bool check(int x,int y)
{
int head=,tail=;
memset(tmp,,sizeof(tmp));
for(int i=;i<=n;i++)
{
while(head<=tail&&l[q[tail]][y]>=l[i][y])
tail--;
q[++tail]=i;
while(q[head]<=i-x)
head++;
tmp[i]+=l[q[head]][y];
}
head=;tail=;
for(int i=;i<=n;i++)
{
while(head<=tail&&r[q[tail]][y]>=r[i][y])
tail--;
q[++tail]=i;
while(q[head]<=i-x)
head++;
tmp[i]+=r[q[head]][y]-;
}
for(int i=x;i<=n;i++)
{
if(tmp[i]>=x)
return ;
}
return ;
} void solve()
{
int tem=ans[k].res;
for(int i=k;i>=;i--)
{
ans[i].res=tem;
int x=ans[i].x;
int y=ans[i].y;
a[x][y]=;
for(int j=;j<=m;j++)
{
l[x][j]=a[x][j]*(l[x][j-]+);
}
for(int j=m;j>=;j--)
{
r[x][j]=a[x][j]*(r[x][j+]+);
}
while(check(tem+,y))
tem++;
}
ans[].res=tem;
for(int i=;i<=k;i++)
{
printf("%d\n",ans[i].res);
}
} int main()
{
init();
dp();
solve();
return ;
}

(完)

CF480E Parking Lot(单调队列+dp然鹅并不是优化)的更多相关文章

  1. POJ 3017 单调队列dp

    Cut the Sequence Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8764   Accepted: 2576 ...

  2. [TyvjP1313] [NOIP2010初赛]烽火传递(单调队列 + DP)

    传送门 就是个单调队列+DP嘛. ——代码 #include <cstdio> ; , t = , ans = ~( << ); int q[MAXN], a[MAXN], f ...

  3. zstu 4237 马里奥的求救——(单调队列DP)

    题目链接:http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4237 这题可以转化为每次可以走g~d+x步,求最大分数,且最大分数的步数最少. ...

  4. 1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP

    1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP 题意 用摄像机观察动物,有两个摄像机,一个可以放在奇数天,一个可以放在偶数天.摄像机在 ...

  5. vijos P1243 生产产品(单调队列+DP)

      P1243生产产品   描述 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产 品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器 ...

  6. POJ 1821 单调队列+dp

    题目大意:有K个工人,有n个墙,现在要给墙涂色.然后每个工人坐在Si上,他能刷的最大范围是Li,且必须是一个连续子区间,而且必须过Si,他刷完后能获得Pi钱 思路:定义dp[i][j]表示前i个人,涂 ...

  7. codeforces 1077F2. Pictures with Kittens (hard version)单调队列+dp

    被队友催着上(xun)分(lian),div3挑战一场蓝,大号给基佬紫了,结果从D开始他开始疯狂教我做人??表演如何AKdiv3???? 比赛场上:A 2 分钟,B题蜜汁乱计数,结果想得绕进去了20多 ...

  8. 【LOJ#10180】烽火传递 单调队列+dp

    题目大意:给定一个 N 个非负整数数组成的序列,每个点有一个贡献值,现选出其中若干数,使得每连续的 K 个数中至少有一个数被选,要求选出的数贡献值最小. 题解:设 \(dp[i]\) 表示考虑了序列前 ...

  9. BZOJ 5281--[Usaco2018 Open]Talent Show(分数规划&单调队列&DP)

    5281: [Usaco2018 Open]Talent Show Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 79  Solved: 58[Sub ...

随机推荐

  1. Redis持久化的方式有哪些?优缺点分别是什么?

    Redis持久化方式        持久化的目的主要是做灾难恢复,数据恢复.由于Redis的数据全都放在内存里面,如果Redis挂了,没有配置持久化的话,重启的时候数据会全部丢失.         突 ...

  2. 利用npm安装/删除/查看包信息

    查看远程服务器上的包的版本信息 npm view webpack version //查看npm服务器上包webpack的最新版本 npm view webpack versions //查看服务器上 ...

  3. web开发基础之HTTP协议

    HTTP协议 HTTP协议简介 超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式.协作式和超媒体信息系统的应用层协议.HTTP是万维网的数 ...

  4. sql 外键 on update cascade 和 on delete cascade 作用区别?

    这是数据库外键定义的一个可选项,用来设置当主键表中的被参考列的数据发生变化时,外键表中响应字段的变换规则的.update 则是主键表中被参考字段的值更新,delete是指在主键表中删除一条记录:on ...

  5. C 自删除技术---批处理方式

    #include<stdio.h> #include<windows.h>#pragma comment(linker, "/subsystem:\"win ...

  6. cobalt strike笔记-CS与MSF,Armitage,Empire互转shell

    0x01 Metasploit派生shell给Cobaltstrike 生成木马: msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata ...

  7. PMBOK(第六版) PMP笔记——《十》第十章(项目沟通管理)

    PMBOK(第六版) PMP笔记——<十>第十章(项目沟通管理) 第十章 项目沟通管理: PM 大多数时间都用在与干系人的沟通上. 第十章有三个过程: 规划沟通管理:根据干系人的需求,制定 ...

  8. Fibonacci 数列和 Lucas 数列的性质、推论及其证明

    Fibonacci 数列 设f(x)=1,x∈{1,2}=f(x−1)+f(x−2),x∈[3,∞)\begin{aligned}f(x)&=1,\quad\quad\quad\quad\qu ...

  9. HDU 1198 Farm Irrigation(状态压缩+DFS)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1198 题目: Farm Irrigation Time Limit: 2000/1000 MS (Ja ...

  10. Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析

    Tomcat启动加载过程(一)的源码解析 今天,我将分享用源码的方式讲解Tomcat启动的加载过程,关于Tomcat的架构请参阅<Tomcat源码分析二:先看看Tomcat的整体架构>一文 ...