线段树+扫描线

经典的扫描线问题

首先将一个矩形看作由竖着的两条边和横着的两条边构成

那分成两次考虑,一次考虑竖边,一次考虑横边

首先考虑横边

如图两个矩形,现将横边擦去,留下竖边,将平面划分成3个区域

在代码实现时,可以从左到右记录端点

那么现在想象一条平行于横边的扫描线不断从下往上扫

当扫到一个矩形的下边,将这条矩形的下边包含的区间覆盖

当扫到一个矩形的上边,将这条矩形的上边包含的区间去除覆盖

那么对于这些被竖线划分的区域,建立一棵线段树维护这些区间是否被覆盖

如最底下的矩形下边,覆盖区间2,3

那么如何统计答案

答案就是上一次线段树维护的总区间被覆盖的长度-当前线段树维护的总区间覆盖的长度的绝对值

如上图,扫描到第2边,上一次覆盖2,3,那此处增加为1区间

那么线段树中维护这个区间被完全覆盖的次数和被覆盖的长度即可

#include <iostream>
#include <algorithm>
#include <map>
#include <cstdio>
#define inf (int)1e9
using namespace std;
int n,w,last,ans;
struct node
{
int a,b,c,d;
}p[5100];
struct tree
{
int l,r,sum;
int len;
}sh[100000];
struct edge
{
int l,r,num,kind;
}a[11000];
bool cmp(edge a,edge b)
{
return (a.num<b.num || (a.num==b.num && a.kind>b.kind));//注意如果同一高度的话,先处理下边的
}
void pushup(int x)
{
if (sh[x].sum>0)//如果当前被完全覆盖,那么当前区间被覆盖的长度为r-l+1
sh[x].len=sh[x].r-sh[x].l+1;
else
if (sh[x].l==sh[x].r)//叶子结点
sh[x].len=0;
else
sh[x].len=sh[x+x].len+sh[x+x+1].len;//一般情况
}
void build(int x,int ll,int rr)
{
sh[x].l=ll;
sh[x].r=rr;
sh[x].sum=sh[x].len=0;
if (ll==rr)
return;
int mid;
mid=(ll+rr)>>1;
build(x+x,ll,mid);
build(x+x+1,mid+1,rr);
}
void change(int x,int ll,int rr,int v)
{
if (sh[x].l>=ll && sh[x].r<=rr)
{
sh[x].sum+=v;
pushup(x);
return;
}
int mid;
mid=(sh[x].l+sh[x].r)>>1;
if (ll<=mid)
change(x+x,ll,rr,v);
if (rr>mid)
change(x+x+1,ll,rr,v);
pushup(x);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d%d%d%d",&p[i].a,&p[i].b,&p[i].c,&p[i].d);
for (int i=1;i<=n;i++)//记录前扫描线要扫到的边
{
w++;
a[w].l=p[i].a;a[w].r=p[i].c;
a[w].kind=1;a[w].num=p[i].b;//下边
w++;
a[w].l=p[i].a;a[w].r=p[i].c;
a[w].kind=-1;a[w].num=p[i].d;//上边
}
build(1,-10000,10000);
sort(a+1,a+1+w,cmp);
last=0;//上一次答案
for (int i=1;i<=w;i++)
{
change(1,a[i].l,a[i].r-1,a[i].kind);
ans+=abs(last-sh[1].len);
last=sh[1].len;
}
w=0;//处理竖边
for (int i=1;i<=n;i++)
{
w++;
a[w].l=p[i].b;a[w].r=p[i].d;
a[w].kind=1;a[w].num=p[i].a;
w++;
a[w].l=p[i].b;a[w].r=p[i].d;
a[w].kind=-1;a[w].num=p[i].c;
}
build(1,-10000,10000);
sort(a+1,a+1+w,cmp);
last=0;
for (int i=1;i<=w;i++)
{
change(1,a[i].l,a[i].r-1,a[i].kind);
ans+=abs(last-sh[1].len);
last=sh[1].len;
}
printf("%d\n",ans);
}

Luogu 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. 洛谷P1856 [USACO5.5]矩形周长Picture

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 更改MySQL 5.7的数据库的存储位置

    操作系统:Windows 10 x64 MySQL安装包版本:mysql-installer-community-5.7.17.0 参考:MySQL 5.7版本的安装使用详细教程+更改数据库data的 ...

  2. sqlserver 分列

    sql server 数据库中某张表(Person)的数据信息是: ID Address 1 平山花园-4单元-12幢-203 2 香山花园-3单元-22幢-304 现在有需求是,将地址信息显示形式改 ...

  3. 连Python产生器(Generator)的原理都解释不了,还敢说Python用了5年?

      最近有很多学Python同学问我,Python Generator到底是什么东西,如何理解和使用.Ok,现在就用这篇文章对Python Generator做一个敲骨沥髓的深入解析.   为了更好地 ...

  4. JS常见加密混淆方式

    目录 前端js常见混淆加密保护方式 eval方法等字符串参数 emscripten WebAssembly js混淆实现 JSFuck AAEncode JJEncode 代码压缩 变量名混淆 字符串 ...

  5. GML与KML的区别

    1.GML是基于XML的地理信息的传输.存储编码,它包括空间的和非空间的地理特征和地理范畴.GML是空 间数据编码.传输.存储.发布的国际标准KML是一个OGC标准 2.GML专注于地理信息的结构与内 ...

  6. 用IPV6隧道连接IPV4孤岛

    hostA和hostB之间是IPV6连接的,但是之前的服务只能支持IPV4,兼容IPV6比较困难.所以用隧道实现hostA和hostB之间用IPV4连接. hostA如下: ip -6 addr ad ...

  7. 集训DP复习整理

    DP复习 集训%你赛2:测绘(审题DP) 经过2000+个小时的努力终于把这道题做出来的蒟蒻通 分析: 这道题我一直没做出来的原因就是因为我太蒟了题面看不懂,题面读懂了,其实不是特别难. 题目翻译: ...

  8. windows 快速安装Python3.7.2

    1.官方下载地址:https://www.python.org/downloads/release/python-372/ 其他地址:http://www.uzzf.com/soft/449550.h ...

  9. CentOS 网卡固定地址配置

    修改4个文件后重启网卡 vim /etc/default/grub GRUB_CMDLINE_LINUX="resume=UUID=05dbb36b-dbba-40a3-ba99-1b044 ...

  10. 通过两行代码即可调整苹果电脑 Launchpad 图标大小

    之前用 13 寸 Mac 的时候我还没觉得,后来换了 16 寸就发现有点不对劲了.因为 Mac 的高分辨率,当你进入 Launchpad 界面,应用图标的大小可能会让你怀疑:这特么是苹果的设计吗?有点 ...