【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) 思路:这个数据范围瞎暴力就过了,但 ...
随机推荐
- django搭建web (五) views.py
http请求: HttpRequest http响应: HttpResponse 所在位置:django.http isinstance(request,HttpResponse) True-> ...
- Beta冲刺Day3
项目进展 李明皇 今天解决的进度 完善了程序的运行逻辑(消息提示框等) 明天安排 前后端联动调试 林翔 今天解决的进度 向微信官方申请登录验证session以维护登录态 明天安排 继续完成维护登录态 ...
- Winserver+Apache+django部署
废话不多说,干活直接上. winserver2012 + django2.0.1 + apache 部署过程 python ==> 3.4 64位 https://www.python.org/ ...
- webapi 使用Autofac 开发经历
2018/4/6 号 早上五点..被手机震动吵醒. 之后直接打开电脑,打算再加强下我自己的webapi这套东西. 虽然三年的工作经验接触了N多框架和各种风格的开发方式,但是让我自己来搞一套实在不会搞, ...
- 裸辞两个月,海投一个月,从Android转战Web前端的求职之路
前言 看到这个标题的童鞋,可能会产生两种想法: 想法一:这篇文章是标题党 想法二:Android开发越来越不景气了吗?前端越来越火了吗? 我一向不喜欢标题党,标题中的内容是我的亲身经历.我是2016年 ...
- vue组件详解(三)——组件通信
组件之间通信可以用下图表示: 组件关系可分为父子组件通信.兄弟组件通信.跨级组件通信. 一.自定义事件 当子组件需要向父组件传递数据时,就要用到自定义事件. 子组件用$emit ()来触发事件,父组件 ...
- windbg查找Kernel32.dll基址
一.首先准备好一个程序,运行起来,用windbg进行附加调试,由于每个windows下的程序都会加载kernel32.dll,因此,找基址的过程是一样的: 二.查看PEB地址: 法一.r $peb ...
- Docker的容器操作
启动一次性运行的容器 入门级例子:从ubuntu:14.04镜像启动一个容器,成功后在容器内部执行/bin/echo 'hello world'命令,如果当前物理机没有该镜像,则执行docker pu ...
- bootstrap表格 之多选数据的获取
使用表格的时候经常会用到多选的功能,比较常用,下面写一个小Dome记录一下 如下:单击批量删除按钮之后,需要获取选中行数据,传值到后台进行处理 一.获取选择行的数据 btnplDel是按钮id:tab ...
- shell:bash环境
1.什么是shell shell一般代表两个层面的意思,一个是命令解释器,比如BASH,另外一个是shell脚本. 命令解释器shell的发展史,sh-csh-ksh-tcsh-bash. 2.命令的 ...