问题来源: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. java第5章学习总结

    学号20145336 <Java程序设计>第5周学习总结 教材学习内容总结 try catch JVM会先尝试执行try区块中的内容,若发生错误且与catch后面的类型相符,则执行catc ...

  2. Flask 扩展 用户会话

    pip install flask-login 接下来创建扩展对象实例: from flask import Flask from flask_login import LoginManager ap ...

  3. js前端对后台数据的获取,如果是汉字则需要添上引号

    js前端对后台数据的获取,如果是汉字则需要添上引号

  4. React 深入系列2:组件分类

    文:徐超,<React进阶之路>作者 授权发布,转载请注明作者及出处 React 深入系列2:组件分类 React 深入系列,深入讲解了React中的重点概念.特性和模式等,旨在帮助大家加 ...

  5. 阿里云API网关(11)外网访问 阿里云API网关内定义的API步骤:

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  6. Docker学习笔记 - Docker容器之间的连接

    学习目标: 容器之间可以相互连接访问:: --link redis:redisAlias 准备工作 FROM ubuntu:14.04 RUN apt-get install -y ping RUN  ...

  7. HTML5的常用新特性你必须知道

    HTML5的常用新特性你必须知道 1 新的 声明 HTML 有多个不同的版本,只有完全明白页面中使用的确切 HTML 版本,浏览器才能完全正确地显示出 HTML 页面.这就是 的用处. 不是 HTML ...

  8. .NET:持续进化的统一开发平台

    阅读文本大概需要 8 分钟. 标题使用的是进化这个词语,是因为 .NET 在不断的努力,也在不断的重构. 这篇文章的更多目的和意义在于科普,俗称"传教". # 持续进化的 .NET ...

  9. 面向对象的PHP(5)

    OOP的好处 封装 封装可以隐藏实现细节,使代码模块化,代码重用 继承 继承可以扩展已存在的代码模块(class),代码重用 多态 为了类在继承和派生的时候,保证实例的某一属性正确调用,接口重用 关键 ...

  10. SpringBoot(四):banner的控制

    banner在springboot中是一个支持可配(banner的样式,banner的颜色,banner的内容).是否显示. 1)banner显示内容配置: 默认springboot如果在src/re ...