[BalkanOI2016]Lefkaritika
题目大意:
一个n*m的格子上有b个障碍物,现在让你往上面放正方形(长宽在格线上)。问可以放多少种边长、位置不同的正方形?
思路:
很容易想到一个O(n^3)的暴力:
首先前缀和,然后枚举某一个顶点和正方形的边长,判断一下正方形里面是否为空,如果空,则为一种满足条件的答案。
枚举边长可以改成二分,这样复杂度是O(n^2 log n)的。
再考虑一个O(n^2)的动规:
用f[i][j]保存以(i,j)为右下角顶点的正方形的个数,显然,如果(i-1,j)(i,j-1)(i-1,j-1)(i,j)上都没有障碍,那么f[i][j]=min(f[i-1][j],f[i][j-1],f[i-1][j-1])+1。
正解是一个O(nb)的奇怪做法:
首先对于障碍物按列再按行排序。
枚举每一行,将在这一行上面的障碍物加入一个数组中。
考虑下边界在当前行的极大化正方形,无非有以下两种情况:
1.上边被顶到。
2.左右两边被顶到。
现在我们让每个障碍物“代表”被其约束的点,记录下行数比它大的左端点和右端点,这一过程可以用单调栈来求。
最后分情况计算出符合条件的正方形个数即可。
#include<stack>
#include<vector>
#include<cstdio>
#include<cctype>
#include<algorithm>
typedef long long int64;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int B=;
struct Point {
int x,y;
bool operator < (const Point &another) const {
if(y==another.y) return x>another.x;
return y<another.y;
}
};
std::vector<Point> a,p;
std::stack<int> q;
int l[B],r[B];
inline int calc(const int &x,const int &y) {
if(!x) return ;
return (int64)(y*-std::min(x,y))*(std::min(x,y)-)/;
}
int main() {
int n=getint(),m=getint(),b=getint();
for(register int i=;i<=b;i++) {
const int x=getint(),y=getint();
a.push_back((Point){x,y});
}
std::sort(a.begin(),a.end());
int64 ans=;
for(register int i=;i<=n;i++) {
p.clear();
p.push_back((Point){i,});
for(register unsigned j=;j<a.size();j++) {
if(a[j].x<=i) {
p.push_back(a[j]);
}
}
p.push_back((Point){i,m+});
while(!q.empty()) q.pop();
q.push();
for(register unsigned i=;i<p.size();i++) {
while(q.size()>&&p[q.top()].x<=p[i].x) q.pop();
l[i]=q.top();
q.push(i);
}
while(!q.empty()) q.pop();
q.push(p.size()-);
for(register unsigned i=p.size()-;i>;i--) {
while(q.size()>&&p[q.top()].x<p[i].x) q.pop();
r[i]=q.top();
q.push(i);
}
for(register unsigned j=;j<p.size();j++) {
ans+=calc(i,p[j].y-p[j-].y-);
}
for(register unsigned j=;j<p.size()-;j++) {
ans+=calc(i-p[j].x,p[r[j]].y-p[l[j]].y-)-calc(i-p[j].x,p[r[j]].y-p[j].y-)-calc(i-p[j].x,p[j].y-p[l[j]].y-);
}
}
printf("%lld\n",ans);
return ;
}
[BalkanOI2016]Lefkaritika的更多相关文章
- 『HGOI 20190917』Lefkaritika 题解 (DP)
题目概述 一个$n \times m$的整点集.其中$q$个点被m被设置为不能访问. 问这个点集中含有多少个不同的正方形,满足不包含任何一个不能访问的点. 对于$50\%$的数据满足$1 \leq n ...
- [BalkanOI2016]Cruise
题目大意: 平面直角坐标系内有n个点,每个点有一个点权. 你从原点p出发,走若干个点然后回到原点. 两个点之间只能笔直走,你的收获为你的路径围起来的区域内的所有店权和除以路径长度. 问最大收益. 思路 ...
随机推荐
- OSI与TCP/IP各层的结构与功能,都有哪些协议
前言: 今天更新一下计算机网络的一些非常重要的知识,可能很多人都不知学计算机网络有什么用,我想说的是它真的比较重要,像咱们学校只要是学计算机这个专业都要学习这门课程.另外大家要是去一些像BAT,阿里, ...
- 【转】Android - Binder机制
以下几篇文章是分析binder机制里讲得还算清楚的 目录 1. Android - Binder机制 - ServiceManager 2. Android - Binder机制 - 普通servic ...
- leetcode 之Plus One(9)
这题需要注意的是最后的进位 vector<int> plusOne(vector<int>& nums,int num) { add(nums, num); } voi ...
- Leetcode 之Simplify Path(36)
主要看//之间的内容:如果是仍是/,或者是.,则忽略:如果是..,则弹出:否则压入堆栈.最后根据堆栈的内容进行输出. string simplifyPath(string const& pat ...
- linux下查看机器配置
查看cpu信息:lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): ...
- J2EE MySQL Date数据保持一致解决方案
1.设置MySQL时区,明确指定 MySQL 数据库的时区,不使用引发误解的 CST show variables like '%time_zone%';set global time_zone = ...
- PHP定界符出现错误
Parse error: syntax error, unexpected end of file, expecting variable (T_VARIABLE) or heredoc end (T ...
- hdu 2448(KM算法+SPFA)
Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- WordPress Shortcode(简码)介绍及使用详解
WordPress 从 2.5 版本开始增加了一个类似 BBCode 标签的 Shortcode API,可以使用它在日志的内容中来给日志内容添加各种功能.Shortcode 这个接口非常容易使用,并 ...
- css 三(清除浮动专题)
1. 三个关于浮动的概念 不浮动float:none; 清除周围的浮动元素 float:both 这是清除浮动的本意 清除子元素浮动对父元素的影响 clearfix 很多人都理解成 ...