[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$ 若最终的矩形不 ...
随机推荐
- rsync同步文件(多台机器同步代码...)
常用组合 rsync -av --delete-after --exclude-from="a.txt" x/x -e ssh x:/x/x a.txt 制定忽略的文件, ...
- vuejs心法和技法
原文地址:http://www.cnblogs.com/kidsitcn/p/5409994.html 所有的vuejs组件都是被扩展的vue实例: var MyComponent = Vue.ext ...
- JS获取元素内容属性以及修改
1.通过document对象
- 在c++中实现反射的初步想法
最近在思考如何在c++中实现反射.事情的起因是这样的:我们服务器是用c++开发的,如果需要写一些测试用的GM指令的话,需要编写完GM代码后重新编译并且重启进程,工序繁琐且比较耗时.因此就有了想用脚本( ...
- js选择checkbox值,组织成key-value形式,传值到后台
最近项目中遇到这样一个问题,接口定义需要传一个Map<String,String[]> params的参数,需要在jsp页面组织数据到后台操作,所以记下来以后难免还会用到. 以下是java ...
- 爬虫基础---HTTP协议理解、网页的基础知识、爬虫的基本原理
一.HTTP协议的理解 URL和URI 在学习HTTP之前我们需要了解一下URL.URI(精确的说明某资源的位置以及如果去访问它) URL:Universal Resource Locator 统一资 ...
- Codeforces 948C Producing Snow(优先队列+思维)
题目链接:http://codeforces.com/contest/948/problem/C 题目大意:给定长度n(n<=1e5),第一行v[i]表示表示第i堆雪的体积,第二行t[i]表示第 ...
- 2015309南皓芯《Java程序设计》实验一(Java开发环境的熟悉)实验报告
一.实验内容及步骤 (一)使用JDK编译.运行简单的java程序 命令行下的程序开发 步骤一(新建文件夹):打开windows下的cmd → 输入cd Code命令进入Code目录 → 输入md 20 ...
- HBase 入门笔记-数据落地篇
一.前言 关于数据落地方面,HBase官网也有相关介绍.本文主要介绍一下实际工作中涉及的数据存储方面的一些经验和技巧,主要涉及表rowkey设计.数据落地方案 二.表设计 相对于MySQL等关系型数据 ...
- Pytest里,mark装饰器的使用,双引号,没引号,这种差别很重要
按最新版的pytest测试框架. 如果只是单一的mark,不要加任何引号. 如果是要作and ,not之类的先把,一定要是双引号! 这个要记清楚,好像和以前版本的书上介绍的不一样,切记! import ...