E. Parking Lot
time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Petya's been bored at work and he is killing the time by watching the parking lot at the office. The parking lot looks from above like an n × m table (a cell of the table corresponds to a single parking spot). Some spots in the parking lot are taken, others are empty.

Petya watches cars riding into the parking lot one by one. After a car settles down at the parking spot, Petya amuzes himself by counting what maximum square of empty spots (i.e. a square subtable) can be seen on the parking lot if we look at it from above. Also, he takes notes of the square's size (side length) in his notebook.

You task is: given the state of the parking lot at the initial moment of time and the information about where the arriving cars park, restore what Petya wrote in his notebook. It is midday, so nobody leaves the lot.

Input

The first line contains three integers nm and k — the sizes of the parking lot and the number of arriving cars after Petya started his watch (1 ≤ n, m, k ≤ 2000). Each of the following n lines contains m characters 'X' and '.', where 'X' means a taken spot and '.' means an empty spot. Each of the next k lines contains a pair of integers xiyi — the number of row and column of the spot the corresponding car takes (1 ≤ xi ≤ n, 1 ≤ yi ≤ m). It is guaranteed that this place was empty. You can assume that a car enters a parking lot only after the previous car successfully finds a spot.

Output

Print k integers — the length of the side of the maximum square of empty spots after the corresponding car has entered the parking lot.

Examples
input
7 8 4
........
X.....X.
........
........
.X......
........
........
1 5
6 4
3 5
4 6
output
5
4
4
3

大致题意:k次操作,每次删掉一个点,删掉后问最大的不含'X'的正方形边长是多少.

分析:一道挺好的题,get了许多技巧.

首先,题目允许离线,并且是每次删点后询问,删点后求答案比较麻烦,可以考虑时间倒流,从后往前添加点进去.类似于bzoj上一道删点求连通块数目的题. 初始化出删掉所有的k个点以后的最大正方形的边长,这个可以用dp来算.接着维护两个数组:up[i][j]和down[i][j].表示(i,j)这个点分别能往上和往下扩展多少位.这些是预处理操作.

因为每次都往里面添加点,所以答案肯定是递增的,而答案不超过2000,所以可以while判断当前答案ans + 1后行不行,直到退出while循环,当前的ans就是答案.比添加这个点之前更大的矩形肯定包含添加进去的这个点.当判断边长为len的正方形行不行时.将所有包含当前点的正方形给枚举出来,看在这个边上的点向上扩展和向下扩展的最小值分别是多少,如果加起来-1正好 ≥ len,则可行,否则不可行.涉及到区间查询操作,可以用线段树搞一搞.对于每次添加的点,只需要在那一列改一下up和down数组,并在那一行维护一下答案就可以了.

犯了一个错误:m写成了n.在写题的时候一般都用n而不用m,碰到这种m用的多的情况可以考虑把m,n互换.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int inf = 0x3f3f3f3f; int n,m,k,a[][],up[][],down[][],ans[],res,f[][];
int min1[ << ],min2[ << ],min11,min22;
char s[][]; struct node
{
int x,y;
}e[]; void init()
{
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (a[i][j] == )
up[i][j] = up[i - ][j] + ;
else
up[i][j] = ;
}
for (int i = n; i >= ; i--)
for (int j = ; j <= m; j++)
{
if (a[i][j] == )
down[i][j] = down[i + ][j] + ;
else
down[i][j] = ;
}
} void jisuan()
{
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
{
if (a[i][j] == )
continue;
f[i][j] = min(f[i-][j],min(f[i][j - ],f[i-][j-])) + ;
res = max(res,f[i][j]);
}
} void pushup(int o)
{
min1[o] = min(min1[o * ],min1[o * + ]);
min2[o] = min(min2[o * ],min2[o * + ]);
} void build(int cur,int o,int l,int r)
{
if (l == r)
{
min1[o] = up[cur][l];
min2[o] = down[cur][l];
return;
}
int mid = (l + r) >> ;
build(cur,o * ,l,mid);
build(cur,o * + ,mid + ,r);
pushup(o);
} int query1(int o,int l,int r,int x,int y)
{
if (x <= l && r <= y)
return min1[o];
int mid = (l + r) >> ,temp = inf;
if (x <= mid)
temp = min(temp,query1(o * ,l,mid,x,y));
if (y > mid)
temp = min(temp,query1(o * + ,mid + ,r,x,y));
return temp;
} int query2(int o,int l,int r,int x,int y)
{
if (x <= l && r <= y)
return min2[o];
int mid = (l + r) >> ,temp = inf;
if (x <= mid)
temp = min(temp,query2(o * ,l,mid,x,y));
if (y > mid)
temp = min(temp,query2(o * + ,mid + ,r,x,y));
return temp;
} bool check(int len,int y)
{
if (len > n || len > m)
return false;
for (int i = max(,y - len + ); i <= m - len + ; i++)
{
int temp1 = query1(,,m,i,i + len - );
int temp2 = query2(,,m,i,i + len - );
if (temp1 + temp2 - >= len)
return true;
}
return false;
} void solve()
{
jisuan();
for (int i = k; i >= ; i--)
{
//printf("%d\n",i);
ans[i] = res;
if (i == )
break;
int x = e[i].x,y = e[i].y;
a[x][y] = ;
up[x][y] = up[x - ][y] + ;
for (int j = x + ; j <= n; j++)
{
if (a[j][y] == )
break;
up[j][y] += up[x][y];
}
down[x][y] = down[x + ][y] + ;
for (int j = x - ; j >= ; j--)
{
if (a[j][y] == )
break;
down[j][y] += down[x][y];
}
build(x,,,m);
while (check(res + ,y))
res++;
}
} int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i = ; i <= n; i++)
{
scanf("%s",s[i] + );
for (int j = ; j <= m; j++)
{
if (s[i][j] == '.')
a[i][j] = ;
else
a[i][j] = ;
}
}
for (int i = ; i <= k; i++)
{
scanf("%d%d",&e[i].x,&e[i].y);
a[e[i].x][e[i].y] = ;
}
init();
solve();
for (int i = ; i <= k; i++)
printf("%d\n",ans[i]); return ;
}

Codeforces 480.E Parking Lot的更多相关文章

  1. CF 480 E. Parking Lot

    CF 480 E. Parking Lot http://codeforces.com/contest/480/problem/E 题意: 给一个n*m的01矩阵,每次可以将一个0修改为1,求最大全0 ...

  2. #2 codeforces 480 Parcels

    题意: 就是有一个用来堆放货物的板,承重力为S.现在有N件货物,每件货物有到达的时间,运走的时间,以及重量,承重,存放盈利.如果这件货物能再运达时间存放,并在指定时间取走的话,就能获得相应的盈利值.货 ...

  3. Codeforces #480 Tutorial

    Problem A,B,C: 简单的模拟,注意A中p mod q时对q=0特殊处理(注意范围) Problem D: Brief Intro: 给定长度为N的数组A,将A中所有连续子序列分成最少的组, ...

  4. Mistakes(Updating)

    1.当调试时发现无法正常调用函数时,检查是否发生爆栈 对于每个栈仅有4MB的空间,开int只能开大约5*10^5. 大数组一定要开全局变量 2.当long long=int*int时会爆int,一定要 ...

  5. [Atcoder Grand Contest 003] Tutorial

    Link: AGC003 传送门 A: 判断如果一个方向有,其相反方向有没有即可 #include <bits/stdc++.h> using namespace std; ]; map& ...

  6. ●CodeForces 480E Parking Lot

    题链: http://codeforces.com/problemset/problem/480/E题解: 单调队列,逆向思维 (在线的话应该是分治做,但是好麻烦..) 离线操作,逆向考虑, 最后的状 ...

  7. Codeforces 46D Parking Lot

    传送门 D. Parking Lot time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  8. Codeforces Round #135 (Div. 2) E. Parking Lot 线段数区间合并

    E. Parking Lot time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  9. Codeforces 219E Parking Lot 线段树

    Parking Lot 线段树区间合并一下, 求当前要占的位置, 不包括两端点的写起来方便一点. #include<bits/stdc++.h> #define LL long long ...

随机推荐

  1. HIVE中的数据怎么导出到hdfs或本地呢

    思路一:重定向 在我不知道工具 ,也不熟悉HIQL语法的情况下,没办法了,只有选择一个最简单粗暴的方法,重定向. 在shell中使用 hive -e 可以在shell中执行hive命令,hive -f ...

  2. HDU 5167 Fibonacci 筛法+乱搞

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5167 题意: 给你一个x,判断x能不能由斐波那契数列中的数相乘得到(一个数可以重复使用) ...

  3. 引用百度bcebos jar 503问题

    最近使用jeecms管理公司各个站点,关于附件部分采用bos进行上传处理. 在引用bosjar的时候,出现503问题,打断点打印异常堆栈信息,也获取不到.后来使用watch,发现BosClientCo ...

  4. java——线性表接口实现

    线性表是存储顺序牌类的数据时最常用的数据结构. 实现线性表有两种方式.第一种是使用数组存储线性表的元素.数组是动态创建的.超过数组的容量时,创建一个 新的更大的数组,并且将当前数组中的元素复制到新建的 ...

  5. QHash和QMultiHash使用

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QHash和QMultiHash使用     本文地址:http://techieliang. ...

  6. 简易四则运算生成程序——添加GUI支持

    项目成员:张金生     张政 工程地址: https://coding.net/u/jx8zjs/p/paperOne/git ssh://git@git.coding.net:jx8zjs/pap ...

  7. PHP中访问控制修饰符

    访问控制修饰符 形式: class  类名{ 访问控制修饰符  属性或方法定义: } 有3个访问修饰符: public公共的:在所有位置都可访问(使用). protected受保护的:只能再该类内部和 ...

  8. Spring Cloud 架构 五大神兽的功能

    什么是微服务 微服务的概念源于2014年3月Martin Fowler所写的一篇文章“Microservices”. 微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调 ...

  9. Mybatis 中 sql 语句的占位符 #{} 和 ${}

    #{} 表示一个占位符号,通过 #{} 可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换.#{} 可以有效防止   sql注入. #{}  ...

  10. 第161天:CSS3实现兼容性的渐变背景(gradient)效果

    CSS实现兼容性的渐变背景(gradient)效果 一.有点俗态的开场白 在对CSS3支持日趋完善的今天,实现兼容性的渐变背景效果已经完全成为可能,本文就将展示如何实现兼容性的渐变背景效果.在众多的浏 ...