问题来源:IOI1998 D2T1

题意:就是在一个平面内给出n个矩形,叫你计算将这些矩形合并以后,新图形的周长。

例如:

上图是原本的矩形们      ---------->合并后的图形

解题思路:拿一条扫描线横着扫一次,遇到左边的边就在这条扫描线上+1,遇到右边的边就在这条扫描线上-1,在边被扫到的时候计算一下线上为0的个数即可。

  因为如果只是单纯的For循环累加,时间会爆,所以我们采用线段树来存这条扫描线的状态优化效率即可。然后竖着再做同样的事做一遍。

  时间效率应该是O(kn)(k是常数)。

附代码:

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#define For(i,a,b) for (int i=a; i<=b; i++)
#define Ford(i,a,b) for (int i=a; i>=b; i--)
#define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
#define mem(qaq,num) memset(qaq,num,sizeof(qaq));
#define ll long long
#define mod 1000000007
#define INF 2000000000
#define mid ((l+r)>>1)
using namespace std;
struct zxy{
int mi,n,mark;
}tr[];
struct edge{
int l,r,h,typ;
}x[],y[];
int n,ans,cnt;
inline int in(){
int x=,f=;
char ch=getchar();
while (ch<''||ch>'') f=ch=='-'?-:,ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x*f;
}
inline void combine(int k){
if (tr[k<<].mi==tr[k<<|].mi) tr[k].n=tr[k<<].n+tr[k<<|].n,tr[k].mi=tr[k<<].mi;
else
if(tr[k<<].mi<tr[k<<|].mi) tr[k].n=tr[k<<].n,tr[k].mi=tr[k<<].mi;
else tr[k].n=tr[k<<|].n,tr[k].mi=tr[k<<|].mi;
return;
}
inline void built(int l,int r,int k){
if (l==r){
tr[k].mi=;
tr[k].n=;
tr[k].mark=;
return;
}
built(l,mid,k<<);
built(mid+,r,k<<|);
combine(k);
tr[k].mark=;
}
inline void pushdown(int k){
int ad=tr[k].mark;
tr[k<<].mark+=ad;
tr[k<<|].mark+=ad;
tr[k<<].mi+=ad;
tr[k<<|].mi+=ad;
tr[k].mark=;
return;
}
inline void update(int l,int r,int a,int b,int k,int ad){
if (l>=a&&b>=r){
tr[k].mark+=ad;
tr[k].mi+=ad;
return;
}
if (tr[k].mark) pushdown(k);
if (a<=mid) update(l,mid,a,b,k<<,ad);
if (b>mid) update(mid+,r,a,b,k<<|,ad);
combine(k);
return;
}
inline int query(int l,int r,int k,int a,int b){
if (l==a&&r==b){
if (tr[k].mi) return ;
return tr[k].n;
}
if (tr[k].mark) pushdown(k);
if (b<=mid) return query(l,mid,k<<,a,b);
if (a>mid) return query(mid+,r,k<<|,a,b);
return query(l,mid,k<<,a,mid)+query(mid+,r,k<<|,mid+,b);
}
void init(){
n=in();
For(i,,n){
int x1=in()+,y1=in()+,x2=in()+,y2=in()+;
x[++cnt].l=x1+,x[cnt].r=x2,x[cnt].h=y1,x[cnt].typ=;
y[cnt].l=y1+,y[cnt].r=y2,y[cnt].h=x1,y[cnt].typ=;
x[++cnt].l=x1+,x[cnt].r=x2,x[cnt].h=y2,x[cnt].typ=;
y[cnt].l=y1+,y[cnt].r=y2,y[cnt].h=x2,y[cnt].typ=;
}
return;
}
bool cmp(edge a,edge b){
return a.h<b.h||(a.h==b.h&&a.typ<b.typ);
}
void work(){
sort(x+,x+cnt+,cmp);
built(,,);
For(i,,cnt)
if (!x[i].typ){
ans+=query(,,,x[i].l,x[i].r);
update(,,x[i].l,x[i].r,,);
}
else{
update(,,x[i].l,x[i].r,,-);
ans+=query(,,,x[i].l,x[i].r);
}
sort(y+,y+cnt+,cmp);
built(,,);
For(i,,cnt)
if (!y[i].typ){
ans+=query(,,,y[i].l,y[i].r);
update(,,y[i].l,y[i].r,,);
}
else{
update(,,y[i].l,y[i].r,,-);
ans+=query(,,,y[i].l,y[i].r);
}
return;
}
int main(){
init();
work();
printf("%d",ans);
}

本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

【IOI1998】Picture(扫描线+线段树)的更多相关文章

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

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

  2. HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  3. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  4. HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)

    Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...

  5. 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树

    题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...

  6. hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

    题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...

  7. P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)

    题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...

  8. HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)

    做这道题之前,建议先做POJ 1151  Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...

  9. [矩形并-扫描线-线段树]Picture

    最近在补数学和几何,没啥好写的,因为已经决定每天至少写一篇了,今天随便拿个题水水. 题目大意:给你N个边平行于坐标轴的矩形,求它们并的周长.(N<=5000) 思路:这个数据范围瞎暴力就过了,但 ...

随机推荐

  1. git(一)快速入门

    1.设置用户名 git config --global user.name '你的用户名' ​ 2.设置用户名邮箱 git config --global user.email '你的邮箱' ​ 3. ...

  2. nyoj 矩形个数

    矩形的个数 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 在一个3*2的矩形中,可以找到6个1*1的矩形,4个2*1的矩形3个1*2的矩形,2个2*2的矩形,2个3 ...

  3. JAVA_SE基础——28.封装

    黑马程序员blog... 面向对象三大特征:1. 封装2. 继承3  多态. 今天我们先学习第一大特征,封装. 封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. 好处:     1. 将变 ...

  4. 在thinkphp框架中使用后台传值过来的数组,在hightcart中使用数组

    js的数组是和php里面数组是不一样的,所以模板文件需要先接受,然后利用Js代码转化之后再使用,接受后台的数组有几种办法 1.后台传过来的json数组,利用Js是可以接受的,然后将json数据利用js ...

  5. 外网访问本地服务器下的web应用

    让本地服务器可以在外网访问的方式有很多,介绍其中一种: 由于本人是在自己电脑上装了一个虚拟机, 测试环境为:虚拟机作为服务器,服务器中装了一个禅道,虚拟机IP192.168.2.221,本人通过tpl ...

  6. Web Api 接收图片

    public async Task<HttpResponseMessage> Upload() { if (!Request.Content.IsMimeMultipartContent( ...

  7. OAuth是什么?

    一.OAuth的概念 1.问题的提出 2.应用场景 3.规范演进 二.OAuth的运行原理 1.参与者 访问私有数据需要用户参与(客户.用户.服务提供者) 访问公共数据不需要用户参与(客户.服务提供者 ...

  8. redis入门(01)redis的下载和安装

    参考链接: 命令手册 : http://www.redis.net.cn/order/ 菜鸟教程: http://www.runoob.com/redis/redis-install.html 一.概 ...

  9. HTTP协议扫盲(三)HTTP协议的请求头列表和分类描述

    一.请求报头和响应报头列表 1.Requests 头列表 Header 解释 示例 Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html Accept ...

  10. maven入门(1-2)settings.xml

    一.简介 settings.xml对于maven来说相当于全局性的配置,用于所有的项目, 当Maven运行过程中的各种配置,例如pom.xml,不想绑定到一个固定的project或者要分配给用户时, ...