题目背景

墙上贴着许多形状相同的海报、照片。它们的边都是水平和垂直的。每个矩形图片可能部分或全部的覆盖了其他图片。所有矩形合并后的边长称为周长。

题目描述

编写一个程序计算周长。

如图1所示7个矩形。

如图2所示,所有矩形的边界。所有矩形顶点的坐标都是整数。

解析

首先想到模拟,这题数据小,直接暴力扫转折点,统计周长的增量就得了。

其实最优解就是这么做的。

TAG里有扫描线,咱就用扫描线吧。

简单来说,还是扫描线同样的思路,做线段覆盖(具体实现可以百度,我懒得写了)。入边权值为+1,出边权值为-1,从下到上扫一遍,从左到右扫一遍,在遇到入边时,统计当前扫描线与上一条之间覆盖线段长度的增量,这个增量具体来说就是做差。

简单的正确性证明:对于上述每一个增量,其都是由入边造成的,那么这个增量最终都会被出边抵消。因此若我们只统计入边造成的增量,其两倍就是总矩形周长。其实非常好想。

参考代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 20010
#define MOD 2520
#define E 1e-12
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct node{
int l,r,h,v;
bool operator<(const node &a)const{
if(a.h==h) return a.v<v;
return a.h>h;
}
}h[N],l[N];
struct tree{
int l,r;
int cnt,dat;
}t[N<<2];
int n,hh[N],hl[N],cmd;
inline void pushup(int p)//线段覆盖
{
if(t[p].cnt){
if(cmd==1) t[p].dat=hh[t[p].r+1]-hh[t[p].l];
else t[p].dat=hl[t[p].r+1]-hl[t[p].l];
}
else if(t[p].l==t[p].r) t[p].dat=0;
else t[p].dat=t[p<<1].dat+t[p<<1|1].dat;
}
inline void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
t[p].cnt=t[p].dat=0;
if(l==r) return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
inline void change(int p,int l,int r,int val)
{
if(l<=t[p].l&&t[p].r<=r){
t[p].cnt+=val;
pushup(p);
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid) change(p<<1,l,r,val);
if(r>mid) change(p<<1|1,l,r,val);
pushup(p);
}
int main()
{
n=read();
int cnth=0,cntl=0,th=0,tl=0;
for(int i=1;i<=n;++i){
int x1,x2,y1,y2;
x1=read(),y1=read(),x2=read(),y2=read();
h[++cnth].l=x1,h[cnth].r=x2,h[cnth].h=y1,h[cnth].v=1;
l[++cntl].l=y1,l[cntl].r=y2,l[cntl].h=x1,l[cntl].v=1;
h[++cnth].l=x1,h[cnth].r=x2,h[cnth].h=y2,h[cnth].v=-1;
l[++cntl].l=y1,l[cntl].r=y2,l[cntl].h=x2,l[cntl].v=-1;
hh[++th]=x1,hh[++th]=x2;
hl[++tl]=y1,hl[++tl]=y2;
}
sort(hh+1,hh+th+1);sort(hl+1,hl+tl+1);
sort(h+1,h+cnth+1);sort(l+1,l+cntl+1);
unique(hh+1,hh+th+1);unique(hl+1,hl+tl+1);
int ans=0,tmp=0;
build(1,1,cnth);
cmd=1;
for(int i=1;i<=cnth;++i){
int x,y;
x=lower_bound(hh+1,hh+th+1,h[i].l)-hh;
y=lower_bound(hh+1,hh+th+1,h[i].r)-hh-1;
change(1,x,y,h[i].v);
if(h[i].v==1)ans+=t[1].dat-tmp;
tmp=t[1].dat;
}
build(1,1,cntl);
cmd=2,tmp=0;
for(int i=1;i<=cntl;++i){
int x,y;
x=lower_bound(hl+1,hl+tl+1,l[i].l)-hl;
y=lower_bound(hl+1,hl+tl+1,l[i].r)-hl-1;
change(1,x,y,l[i].v);
if(l[i].v==1)ans+=t[1].dat-tmp;
tmp=t[1].dat;
}
ans<<=1;
cout<<ans<<endl;
return 0;
}

P1856 [USACO5.5]矩形周长Picture[扫描线]的更多相关文章

  1. luogu P1856 [USACO5.5]矩形周长Picture 扫描线 + 线段树

    Code: #include<bits/stdc++.h> #define maxn 200007 #define inf 100005 using namespace std; void ...

  2. P1856 [USACO5.5]矩形周长Picture

    P1856 [USACO5.5]矩形周长Picture $len$            $sum$              $num$             $flag\_l$ $flage\_ ...

  3. 洛谷P1856 [USACO5.5]矩形周长Picture

    题目背景 墙上贴着许多形状相同的海报.照片.它们的边都是水平和垂直的.每个矩形图片可能部分或全部的覆盖了其他图片.所有矩形合并后的边长称为周长. 题目描述 编写一个程序计算周长. 如图1所示7个矩形. ...

  4. Luogu P1856 [USACO5.5]矩形周长Picture

    线段树+扫描线 经典的扫描线问题 首先将一个矩形看作由竖着的两条边和横着的两条边构成 那分成两次考虑,一次考虑竖边,一次考虑横边 首先考虑横边 如图两个矩形,现将横边擦去,留下竖边,将平面划分成3个区 ...

  5. [题解]P1856 [USACO5.5]矩形周长Picture

    Loli 考试的题目之一 题目地址 \(N^2\)做法 #include <cstdio> #include <cstring> #define re register #de ...

  6. luogu1856 [USACO5.5]矩形周长Picture

    看到一坨矩形就要想到扫描线.(poj atantis) 我们把横边竖边分开计算,因为横边竖边其实没有区别,以下论述全为考虑竖边的. 怎样统计一个竖边对答案的贡献呢?答:把这个竖边加入线段树,当前的总覆 ...

  7. [USACO5.5] 矩形周长Picture

    https://www.luogu.org/problemnew/show/P1856 1.每个矩形由两条横向边和两条纵向边组成. 2.对于横向边,按纵坐标排序.设当前讨论的边为 A [s , t] ...

  8. Luogu1856 [USACO5.5]矩形周长Picture (线段树扫描线)

    对于横轴,加上与上一次扫描的差值:对于竖轴,加上高度差与区间内不相交线段\(*2\)的积: 难点在pushdown,注意维护覆盖关系.再就注意负数 #include <iostream> ...

  9. 「USACO5.5」矩形周长Picture

    题目描述 墙上贴着许多形状相同的海报.照片.它们的边都是水平和垂直的.每个矩形图片可能部分或全部的覆盖了其他图片.所有矩形合并后的边长称为周长. 编写一个程序计算周长. 如图1所示7个矩形. 如图2所 ...

随机推荐

  1. mysq5.7 主主同步

    db01  172.21.0.10 db02  172.21.0.14 一.安装数据库看上一遍博客 修改配置文件  db01  172.21.0.10 [root@VM_0_10_centos mys ...

  2. python中__init__.py的作用、module和package

    控制包的导入行为: 1.声明当前文件是一个可导入的包: 2.如果当下包下有多个.py文件使用__ all__ = [ '模块名'],也就是form XXX import YYY module和pack ...

  3. 008 SpringCloud 学习笔记4-----Ribbon负载均衡

    1.Ribbon概述 实际环境中,我们往往会开启很多个itcast-service-provider的集群.此时我们获取的服务列表中就会有多个,到底该访问哪一个呢? Eureka中已经帮我们集成了负载 ...

  4. HTML登录注册页面简单实现

    github:传送门 , 码云: 传送门 效果参考: 登录页面,注册页面 使用了bootstrap,jQuery. 后端使用的CGI处理表单,存入MySQL数据库.(之后更新) 登录页面源码 < ...

  5. 「UR#5」怎样跑得更快

    「UR#5」怎样跑得更快 膜这个您就会了 下面是复读机mangoyang 我们要求 \[ \sum_{j=1}^n \gcd(i,j)^{c-d} j^d x_j=\frac{b_i}{i^d} \] ...

  6. SqlServer调用OPENQUERY函数远程执行增删改查

    /* OPENQUERY函数,远程执行数据库增删改查 关于OPENQUERY函数第二个参数不支持拼接变量的方案 方案1:将OPENQUERY语句整个拼接为字符串,再用EXEC执行该字符串语句 方案2: ...

  7. Python调用Matlab2014b引擎

    用惯Python的你,是不是早已无法忍受matplotlib那丑陋无比的图以及蛋疼无比部署依赖? 当当当当,Matlab2014b的Python Engine API现已加入豪华午餐. 上次写了一篇文 ...

  8. (1)ASP.NET Core 应用启动Startup类简介

    1.前言 Core与早期版本的 ASP.NET 对比,配置应用程序的方式的 Global.asax.FilterConfig.cs和RouteConfig.cs 都被Program.cs 和 Star ...

  9. KIP-382: MirrorMaker 2.0

    Status Motivation Public Interfaces Proposed Changes Remote Topics, Partitions Aggregation Cycle det ...

  10. mysql数据库的安装和连接测试并给root用户赋密码

    一.mysql数据库的安装 Windows下MySQL的配置 以 MySQL 5.1 免安装版为例, 下载 mysql-noinstall-5.1.69-win32.zip ( 官方下载页: http ...