题目背景

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

题目描述

编写一个程序计算周长。

如图1所示7个矩形。

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

输入输出格式

输入格式:

输入文件的第一行是一个整数N(0<=N<5000),表示有多少个矩形。接下来N行给出了每一个矩形左下角坐标和右上角坐标(所有坐标的数值范围都在-10000到10000之间)。

输出格式:

输出文件只有一个正整数,表示所有矩形的周长。

这里提供一种线段树实现扫描线的方法:
碰到下边就在图中投影一条线段,遇到上边就在图中删除一条线段.
对于每个节点,我们维护这几个值:
$numv[o],len[o],lflag[o],rflag[o],sumv[o]$
其中分别代表: 该区间左右端点个数,区间被覆盖总长度,线段树中左儿子是否被覆盖,线段树中右儿子是否被覆盖,该点被覆盖的 线段数目
在节点 $x$ 插入了一个线段,节点 $x$ 维护 $[l,r]$ ,直接在对应的 
$sumv[o]$ 上加上一即可,删除操作时类似的,将 $sumv[o]$ 减一就行.
考虑 $pushup$ 函数:
假设 $sumv[o]$ > 1, 说明该区间正被一个线段覆盖着,那么显然 $lflag[o]=rflag[o]=1$, $len[o]=r-l+1$.
$sumv[o]=0$,则该区间并没又有被一个完整的区间所覆盖. 
$len[o]=len[ls]+len[rs]$
$numv[o]=numv[ls]+numv[rs]$
$if(rflag[ls](and)lflag[rs])--numv[o]$
$lflag[o]=lflag[ls]$
$rflag[o]=rflag[rs]$      
#include<bits/stdc++.h>
#define maxn 200007
#define inf 100005
using namespace std;
void setIO(string s)
{
string in=s+".in";
freopen(in.c_str(),"r",stdin);
}
struct Edge
{
int l,r,h,flag;
}edges[maxn];
int n;
namespace tr
{
#define ls lson[o]
#define rs rson[o]
#define mid ((l+r)>>1)
int tot;
int lson[maxn<<2],rson[maxn<<2],lflag[maxn<<2],rflag[maxn<<2],sumv[maxn<<2],numv[maxn<<2],len[maxn<<2];
int newnode() { return ++tot; }
void pushup(int o,int l,int r)
{
if(sumv[o])
{
numv[o]=1;
len[o]=r-l+1;
lflag[o]=rflag[o]=1;
}
else
{
len[o]=len[ls]+len[rs];
numv[o]=numv[ls]+numv[rs];
if(rflag[ls]&&lflag[rs]) --numv[o];
lflag[o]=lflag[ls];
rflag[o]=rflag[rs];
}
}
void add(int &o,int l,int r,int L,int R,int v)
{
if(!o) o=newnode();
if(l>=L&&r<=R)
{
sumv[o]+=v;
pushup(o,l,r);
return;
}
if(L<=mid) add(ls,l,mid,L,R,v);
if(R>mid) add(rs,mid+1,r,L,R,v);
pushup(o,l,r);
}
};
bool cmp(Edge a,Edge b)
{
if(a.h==b.h) return a.flag > b.flag;
else return a.h < b.h;
}
int main()
{
// setIO("input");
scanf("%d",&n);
int a,b,c,d,i,ed=0,j,root=0,last=0,ans=0;
for(i=1;i<=n;++i)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
edges[++ed].l=a,edges[ed].r=c-1,edges[ed].h=b,edges[ed].flag=1; // 加边
edges[++ed].l=a,edges[ed].r=c-1,edges[ed].h=d,edges[ed].flag=-1; // 删边
}
sort(edges+1,edges+1+ed,cmp);
for(i=1;i<=ed;++i)
{
tr::add(root,-inf,inf,edges[i].l,edges[i].r,edges[i].flag);
ans+=abs(tr::len[root]-last);
last=tr::len[root];
ans+=((tr::numv[root]<<1)*(edges[i+1].h-edges[i].h));
}
printf("%d\n",ans);
return 0;
}

  

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

  1. P1856 [USACO5.5]矩形周长Picture[扫描线]

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

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

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

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

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

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

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

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

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

  6. 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线

    51nod 1206 Picture 矩形周长求并 | 线段树 扫描线 #include <cstdio> #include <cmath> #include <cstr ...

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

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

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

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

  9. POJ1151Atlantis 矩形面积并 扫描线 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1151 题意概括 给出n个矩形,求他们的面积并. n<=100 题解 数据范围极小. 我们分3种 ...

随机推荐

  1. 【ACM】 hdu_1090_A+BII_201307261100

    A+B for Input-Output Practice (II)Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/3276 ...

  2. Linux模块化机制和module_init

    致谢: 微信公众号:嵌入式企鹅圈 每天都新增爱好者关注,感谢大家的支持和大牛们的建议. 本人将竭力出品很多其它优质的原创文章回馈大家的厚爱. 引子:模块化机制长处 模块化机制(module)是Linu ...

  3. IOS_OC_Category

    1.Category概述 那的Category的使用场景有那些呢: 1.类包括了非常多个方法实现,而这些方法须要不同团队的成员来实现 2.当你在使用基础类库中的类时,你不想继承这些类而仅仅想加入一些方 ...

  4. Oracle 堵塞(blocking blocked)

    堵塞是DBA常常碰到的情形,尤其是不良的应用程序设计的堵塞将导致性能严重下降直至数据库崩溃. 对DBA而言,有必要知道怎样定位到当前系统有哪些堵塞,究竟谁是堵塞者,谁是被堵塞者.本文对此给出了描写叙述 ...

  5. Codeforces Round #330 (Div. 2) D. Max and Bike 二分

    D. Max and Bike For months Maxim has been coming to work on his favorite bicycle. And quite recently ...

  6. K度限制MST poj 1639

    /* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...

  7. TF101出现“DMClient已停止”处理办法

    设定->应用程式->全部->DMClient强制停止 然后 清除数据 然后 重开机 测试通过.

  8. bzoj2132: 圈地计划(无比强大的最小割)

    2132: 圈地计划 题目:传送门 简要题意: 给出一个矩阵,一共n*m个点,并给出三个收益矩阵.A矩阵表示这个点建A的可取收益,B矩阵表示这个点建B的可取收益,C矩阵表示如果相邻(有且仅有一条公共边 ...

  9. git出错调试

    https://stackoverflow.com/questions/6178401/how-can-i-debug-git-git-shell-related-problems git_trace ...

  10. CodeForces - 749C Voting

    C. Voting time limit per test 1 second memory limit per test 256 megabytes input standard input outp ...