[Arc063F] Snuke's Coloring 2
[Arc063F] Snuke's Coloring 2
题目大意
给你一个网格图,一些点上有标记,求边长最大空白矩形。
试题分析
专门卡\(\log^2 n\)系列。
首先由题意我们可以找到答案的下界:\(\min(H,W)\times 2+2\)。
那么就是说这个矩形的周长如果要大于下界肯定会跨越中轴线\(H\)或\(W\),那么我们只需要在两边枚举即可。
这个东西看起来没什么用,我们姑且将其当作常数优化,但是在后面的讨论中它极大地简化了问题。
继续考虑传统扫描线的方向,那么看看当我们确定了任意一个边界的时候可以干什么。
假定这里枚举的是右边界,然后左边界又没有东西可以维护了,那就直接让线段树维护:枚举右边界到点\(i\),左边界为下标时的周长最大值。
现在就是扫描线的问题了,既然维护的是右边界和左边界,那么就肯定按照x轴从左向右扫。
对于上下界的部分,对于每个点维护两个单调栈,方向如下图。
但是这样一来的话就需要开主席树模拟单调栈,相当恶心,并且多了一个log。
怎么办呢?上面我们说过,这个矩形肯定会跨越中轴线,也就是说,我们只需要在中轴线上面维护一个,在下面维护一个单调栈就足够了。
于是,我们的矩形变成了这个样子:
那么下面就是考虑在单调栈进出的时候去更新线段树了,这里建议画一下图:
- 我们枚举点并加入左边界的考虑部分,因为这个点相对于上一个点会向上移动,加入这个点的时候首先需要弹掉单调队列在它下面的点,然后要把编号在\({id_{stack_{top}}}\)和\({id_{stack_{last\space top}}}\)之间的这些点都减去\(y_i-y_{id_{stack_{top}}}\),因为需要将当前右边界转到下一个点上去。
- 对于上面也是相同,只需要维护一个如图反着的单调队列即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
//#include<ctime>
//#include<cmath>
//#include<queue>
using namespace std;
#define LL long long
inline LL read(){
LL x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const LL INF = 2147483600;
const LL MAXN = 500010;
struct data{
LL x,y;
}p[MAXN+1],a[MAXN+1],b[MAXN+1];
data make_data(LL xx,LL yy){
data a; a.x=xx; a.y=yy; return a;
}
LL N,W,H;
LL tag[MAXN<<2],tr[MAXN<<2];
bool cmp(data a,data b){
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
inline void tage_lazy(LL rt){
if(!tag[rt]) return ;
tag[rt<<1]+=tag[rt]; tag[rt<<1|1]+=tag[rt];
tr[rt<<1]+=tag[rt]; tr[rt<<1|1]+=tag[rt];
tag[rt]=0;
return ;
}
inline void update(LL rt,LL l,LL r,LL L,LL R,LL k){
if(L>R) return ;
if(L<=l&&R>=r){tr[rt]+=k; tag[rt]+=k; return ;} tage_lazy(rt);
LL mid=(l+r)>>1; if(L<=mid) update(rt<<1,l,mid,L,R,k);
if(R>mid) update(rt<<1|1,mid+1,r,L,R,k);
tr[rt]=max(tr[rt<<1],tr[rt<<1|1]); return ;
} LL ans=0;
inline void work(){
sort(p+1,p+N+1,cmp);
memset(tr,0,sizeof(tr));
memset(tag,0,sizeof(tag));
LL l=0,r=0;
for(LL i=1;i<=N;i++){
if(p[i].y<=(H>>1)){
LL lat=i-1;
while(l&&a[l].y<p[i].y){
update(1,1,N,a[l].x,lat,a[l].y-p[i].y);
lat=a[l].x-1; --l;
} if(lat!=i-1){
a[++l]=make_data(lat+1,p[i].y);
}
} else{
LL lat=i-1;
while(r&&b[r].y>p[i].y){
update(1,1,N,b[r].x,lat,p[i].y-b[r].y);
lat=b[r].x-1; --r;
} if(lat!=i-1){
b[++r]=make_data(lat+1,p[i].y);
}
} a[++l]=make_data(i,0);
b[++r]=make_data(i,H); update(1,1,N,i,i,H-p[i].x);
ans=max(ans,tr[1]+p[i+1].x);
} return ;
}
int main(){
//freopen("a.in","r",stdin);
//freopen(".out","w",stdout);
W=read(),H=read(); N=read();
for(LL i=1;i<=N;i++){
p[i].x=read(),p[i].y=read();
} p[++N].x=0; p[N].y=0; p[++N].x=W; p[N].y=H; work(); swap(W,H);
for(LL i=1;i<=N;i++){
swap(p[i].x,p[i].y);
} work(); printf("%lld\n",ans*2);
return 0;
}
[Arc063F] Snuke's Coloring 2的更多相关文章
- [arc063F]Snuke's Coloring 2-[线段树+观察]
Description 传送门 Solution 我们先不考虑周长,只考虑长和宽. 依题意得答案下限为max(w+1,h+1),并且最后所得一定是个矩形(矩形内部无点). 好的,所以!!!答案一定会经 ...
- ARC063F すぬけ君の塗り絵 2 / Snuke's Coloring 2
题面 一句话题面:给你一些点,求这些点之中夹的最大的矩形周长.(考虑边界) Solution 首先是一个结论,答案矩形一定经过\(x=\frac{w}{2}\)或经过\(y=\frac{h}{2}\) ...
- 【ARC 063F】Snuke's Coloring 2
Description There is a rectangle in the xy-plane, with its lower left corner at (0,0) and its upper ...
- すぬけ君の塗り絵 / Snuke's Coloring AtCoder - 2068 (思维,排序,贡献)
Problem Statement We have a grid with H rows and W columns. At first, all cells were painted white. ...
- Snuke's Coloring 2-1
There is a rectangle in the xy-plane, with its lower left corner at (0,0) and its upper right corner ...
- AtCoder Regular Contest 063 F : Snuke’s Coloring 2 (线段树 + 单调栈)
题意 小 \(\mathrm{C}\) 很喜欢二维染色问题,这天他拿来了一个 \(w × h\) 的二维平面 , 初始时均为白色 . 然后他在上面设置了 \(n\) 个关键点 \((X_i , Y_i ...
- 2018.09.22 atcoder Snuke's Coloring 2(线段树+单调栈)
传送门 就是给出一个矩形,上面有一些点,让你找出一个周长最大的矩形,满足没有一个点在矩形中. 这个题很有意思. 考虑到答案一定会穿过中线. 于是我们可以把点分到中线两边. 先想想暴力如何解决. 显然就 ...
- 2018.09.19 atcoder Snuke's Coloring(思维题)
传送门 谁能想到这道题会写这么久. 本来是一道很sb的题啊. 就是每次选一个点只会影响到周围的九个方格,随便1e9进制就可以hash了,但是我非要作死用stl写. 结果由于技术不够高超,一直调不出来. ...
- [atARC063F]Snuke's Coloring 2
首先,可以通过将所有$x_{i}=0$都选择第1类,其余选第2类,构造出一个以$(0,0)$和$(1,h)$为左下角和右上角的矩形,答案即为$2h+2$,类似地还可以构造出$2w+2$ 若最终的矩形不 ...
随机推荐
- oracle建表,设置主键,修改属性等
--建表 create table book( book_id number(10), book_name varchar2(20), book_price number(10,2), book_au ...
- flask基础之AppContext应用上下文和RequestContext请求上下文(六)
前言 应用上下文和请求上下文存在的目的,官方文档讲的很清楚,可参考: http://www.pythondoc.com/flask/appcontext.html 应用上下文对象在没有请求的时候是可以 ...
- 一个不错的linux学习资料下载的网址
本文比较完整的讲述GNU make工具,涵盖GNU make的用法.语法.同时重点讨论如何为一个工程编写Makefile.作为一个Linux程序员,make工具的使用以及编写Makefile是必需的. ...
- 对于Linux平台下C语言开发中__sync_函数的认识(转)
reference:http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html#Atomic-Builtins A built-i ...
- C#中HttpWebRequest的GetRequestStream执行的效率太低,甚至偶尔死掉
为了提高httpwebrequest的执行效率,查到了一些如下设置 request.ServicePoint.Expect100Continue = false; request.ServicePoi ...
- 04 Effective Go 高效的go语言 重点内容
Effective Go 高效的go语言 Introduction 介绍 Examples 例子 Formatting 格式 Commentary 评论 Names 名字 Package names ...
- Oracle 函数 “数据控制,指定某些人只能查看他权限范围内的信息”
create or replace function work_plan_mask (p_schema VARCHAR2,p_table VARCHAR2) return Varchar2 AS -- ...
- 洛谷P2680运输计划
传送门啦 要求的就是,把树上的一条边的权值设为0之后,所有路径中的最大值的最小值. 首先二分最大值,假设某次二分的最大值为x,我们首先找出所有大于x的路径(也就是我们需要通过改权缩短的路径),并把路径 ...
- python_docx制作word文档
一.docx模块 Python可以利用python-docx模块处理word文档,处理方式是面向对象的.也就是说python-docx模块会把word文档,文档中的段落.文本.字体等都看做对象,对对象 ...
- python中round(四舍五入)的坑
python中的round函数不能直接拿来四舍五入,一种替代方式是使用Decimal.quantize()函数. 具体内容待补. >>> round(2.675, 2) 2.67 可 ...