【IOI1998】Picture(扫描线+线段树)
问题来源: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(扫描线+线段树)的更多相关文章
- luogu P1856 [USACO5.5]矩形周长Picture 扫描线 + 线段树
Code: #include<bits/stdc++.h> #define maxn 200007 #define inf 100005 using namespace std; void ...
- HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树
[BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...
- 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 ...
- 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树
题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...
- hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积
题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...
- P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)
题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...
- HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)
做这道题之前,建议先做POJ 1151 Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...
- [矩形并-扫描线-线段树]Picture
最近在补数学和几何,没啥好写的,因为已经决定每天至少写一篇了,今天随便拿个题水水. 题目大意:给你N个边平行于坐标轴的矩形,求它们并的周长.(N<=5000) 思路:这个数据范围瞎暴力就过了,但 ...
随机推荐
- git(一)快速入门
1.设置用户名 git config --global user.name '你的用户名' 2.设置用户名邮箱 git config --global user.email '你的邮箱' 3. ...
- nyoj 矩形个数
矩形的个数 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 在一个3*2的矩形中,可以找到6个1*1的矩形,4个2*1的矩形3个1*2的矩形,2个2*2的矩形,2个3 ...
- JAVA_SE基础——28.封装
黑马程序员blog... 面向对象三大特征:1. 封装2. 继承3 多态. 今天我们先学习第一大特征,封装. 封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. 好处: 1. 将变 ...
- 在thinkphp框架中使用后台传值过来的数组,在hightcart中使用数组
js的数组是和php里面数组是不一样的,所以模板文件需要先接受,然后利用Js代码转化之后再使用,接受后台的数组有几种办法 1.后台传过来的json数组,利用Js是可以接受的,然后将json数据利用js ...
- 外网访问本地服务器下的web应用
让本地服务器可以在外网访问的方式有很多,介绍其中一种: 由于本人是在自己电脑上装了一个虚拟机, 测试环境为:虚拟机作为服务器,服务器中装了一个禅道,虚拟机IP192.168.2.221,本人通过tpl ...
- Web Api 接收图片
public async Task<HttpResponseMessage> Upload() { if (!Request.Content.IsMimeMultipartContent( ...
- OAuth是什么?
一.OAuth的概念 1.问题的提出 2.应用场景 3.规范演进 二.OAuth的运行原理 1.参与者 访问私有数据需要用户参与(客户.用户.服务提供者) 访问公共数据不需要用户参与(客户.服务提供者 ...
- redis入门(01)redis的下载和安装
参考链接: 命令手册 : http://www.redis.net.cn/order/ 菜鸟教程: http://www.runoob.com/redis/redis-install.html 一.概 ...
- HTTP协议扫盲(三)HTTP协议的请求头列表和分类描述
一.请求报头和响应报头列表 1.Requests 头列表 Header 解释 示例 Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html Accept ...
- maven入门(1-2)settings.xml
一.简介 settings.xml对于maven来说相当于全局性的配置,用于所有的项目, 当Maven运行过程中的各种配置,例如pom.xml,不想绑定到一个固定的project或者要分配给用户时, ...