[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$ 若最终的矩形不 ...
随机推荐
- 信息安全学习笔记--XSS
一.XSS简介 XSS (Cross Site Scripting)是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中.比如这些代码包括HTML代 ...
- Go语言fmt库的print函数源码解析
// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a B ...
- Python——杂记
python 最近出错总结: 1.而for..in ..中不要用else if x in y: print else: print2.def fibs(num): ... ...
- Html5使用history对象history.pushState()和history.replaceState()方法添加和修改浏览历史记录
根据网上参考自己做个笔记:参考网址:http://javascript.ruanyifeng.com/bom/history.html history.pushState() HTML5为histor ...
- C++学习之路(十一):C++的初始化列表
结论: 1.在C++中,成员变量的初始化顺序与变量在类型中的声明顺序相同,而与他们在构造函数的初始化列表中的顺序无关. 2.构造函数分为两个阶段执行:1)初始化阶段:2)普通的计算阶段,表现为赋值操作 ...
- Linux 内核驱动--多点触摸接口【转】
转自:http://blog.csdn.net/joard_yang/article/details/6225937 译自:linux-2.6.31.14/Documentation/input/mu ...
- HTML语义化(2016/3/16更新)
目录 什么是HTML语义化? 为什么要语义化 常用标签的语义 HTML5新元素 一.什么是HTML语义化? 简单来讲就是:每个标签做自己的事,使得能够被机器直接读懂. 二.为什么要语义化? 1.更容易 ...
- centos7上安装指定版本gitlab
当我们在做gitlab服务器迁移的时候需要两台服务器中的gitlab相同,如果不同则不让回复git备份.这样我们就要安装指定版本的gitlab. 1. 安装依赖软件 yum -y install po ...
- 无需编译app切换线上、测试环境
在咱们测试过程中,经常需要切换测试环境和线上环境.大致有如下几个方案. 一.服务器地址编译到app中 此种方式需要在代码里保存两套配置,一套指向线上,一套指向测试.通过编译参数分别生成测试包.线上包. ...
- 读书笔记--C陷阱与缺陷(六)
第六章 1.预处理器:预处理器先对代码进行必要的转换处理,简化编程者的工作. 它的重要原因有以下两点: a. 假如要将程序中出现的所有实例都加以修改,但希望只改动程序一处数值,重新编译实现. 预处理器 ...