题目原网址:http://poj.org/problem?id=1177

题目中文翻译:

解题思路:

总体思路:

1.沿X轴离散化建树

2.按Y值从小到大排序平行与X轴的边,然后顺序处理

如果遇到矩形下面那条边则插入到线段树中,遇到矩形上面的边则将相应的边删除掉

根据线段树当前的状态统计长度

第二点是本题的核心思想,偶再举个例:


  第一次求出的部分很好理解.

第二次求出的为什么会少了中间那部分.那是因为插入的新线段覆盖了第一条,此时线段树返回的长度是新的那一条的长度,将这个值再减去上次的就少了中间那部分

第三次因为是矩形的上边,所以要删除在那条长的线段.此时的线段树返回的则是第一次的长度,将此值减去第二次返回值,再取其负值就是红色X轴那部分了

最后那条X轴的,再补上就行了.

需要注意的就是离散化以后一定要去掉重复元素,否则会出错的。

转载自:传送门

AC代码:

 #include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; struct kkk {
int l,r;//线段树表示区间范围
int cnt;//有效长度
int lf,rf;//实际左右端点
int numseg;//分支数,一个分支对应两条竖线
int c;//记录覆盖情况
bool lc,rc;//左右半覆盖情况
}s[]; struct ll {
int y;
int x1,x2;
int f;//表示出入边,入边为1,出边为-1(自己想想为什么)
}l[]; int x[]; bool cmp(ll a,ll b) {
return a.y < b.y;
} void build(int i,int le,int r) {//建树
s[i].l = le;
s[i].r = r;
s[i].lf = x[le];
s[i].rf = x[r];
s[i].cnt = ;
s[i].numseg = ;
s[i].c = ;
s[i].lc = s[i].rc = false;
if(le + == r) return ;
int mid = (le + r) / ;
build(i << ,le,mid);
build((i << ) | ,mid,r);
} void calen(int i) {//计算长度
if(s[i].c > ) {
s[i].cnt = s[i].rf - s[i].lf;
s[i].numseg = ;
s[i].lc = s[i].rc = true;
return ;
}
if(s[i].l + == s[i].r) {
s[i].cnt = ;
s[i].numseg = ;
s[i].lc = s[i].rc = false;
}
else {
s[i].cnt = s[i<<].cnt + s[(i<<)|].cnt;
s[i].lc = s[i<<].lc;
s[i].rc = s[(i<<)|].rc;
s[i].numseg = s[i<<].numseg + s[(i<<)|].numseg;
if(s[i<<].rc&&s[(i<<)|].lc) s[i].numseg--;
}
} void update(int i,ll e) {
if(s[i].lf == e.x1 && s[i].rf == e.x2) {
s[i].c += e.f;
calen(i);
return ;
}
if(e.x2 <= s[i<<].rf) update(i << ,e);
else if(e.x1 >= s[(i<<)|].lf) update((i<<) | ,e);
else {
ll temp = e;
temp.x2 = s[i<<].rf;
update(i << ,temp);
temp = e;
temp.x1 = s[i<<|].lf;
update((i<<)|,temp);
}
calen(i);
} int main()
{
int x1,y1,x2,y2;
int n;
while(scanf("%d",&n) == ) {
int t = ;
for(int i = ;i < n; i++) {
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
l[t].x1 = x1;
l[t].x2 = x2;
l[t].y = y1;
l[t].f = ;
x[t++] = x1;
l[t].x1 = x1;
l[t].x2 = x2;
l[t].y = y2;
l[t].f = -;
x[t++] = x2;
}
sort(l,l+t,cmp);
sort(x,x+t);
int m = unique(x,x+t) - x;
build(,,m-);
int ans = ;
int last = ;
for(int i = ;i < t - ; i++) {
update(,l[i]);
ans += s[].numseg * * (l[i+].y - l[i].y);
ans += abs(s[].cnt - last);
last = s[].cnt;
}
update(,l[t-]);
ans += abs(s[].cnt - last);
printf("%d\n",ans);
}
return ;
}

POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)的更多相关文章

  1. poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)

    题目链接 题意:给出n个矩形,每个矩形给左下 和 右上的坐标,求围成的周长的长度. 分析: 首先感谢大神的博客,最近做题经常看大神的博客:http://www.cnblogs.com/kuangbin ...

  2. poj 1177 --- Picture(线段树+扫描线 求矩形并的周长)

    题目链接 Description A number of rectangular posters, photographs and other pictures of the same shape a ...

  3. 覆盖的面积 HDU - 1255 线段树+扫描线+离散化 求特定交叉面积

    #include<cstdio> #include<map> #include<algorithm> using namespace std; ; struct N ...

  4. HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...

  5. HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  6. hdu1255 覆盖的面积 线段树+里离散化求矩形面积的交

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 求矩形面积的交的线段树题目,刚做了求并的题目,再做这个刚觉良好啊,只要再加一个表示覆盖次数大于1 ...

  7. Picture POJ - 1177 (线段树-扫描线)

    A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wa ...

  8. POJ 1177 Picture(线段树周长并)

      描述 A number of rectangular posters, photographs and other pictures of the same shape are pasted on ...

  9. hdu1542 Atlantis (线段树+扫描线+离散化)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

随机推荐

  1. wxWidgets刚開始学习的人导引(6)——wxWidgets学习材料清单

    wxWidgets刚開始学习的人导引全文件夹   PDF版及附件下载 1 前言2 下载.安装wxWidgets3 wxWidgets应用程序初体验4 wxWidgets学习资料及利用方法指导5 用wx ...

  2. linux i2c 标准接口(二)

    驱动程序操作法:i2c设备的驱动也可以通过普通的设备驱动实现,像往常的驱动一样实现,然后在应用层就可以像读取普通文件一样操作,无需再考虑读写时序.其实普通的设备驱动也可以用两种方法实现, 1)构建字符 ...

  3. 初解C#类、结构、弱引用

    一.类 类中的数据和函数称为类的成员 数据成员是包含类的数据----字段.常量和事件的成员.数据成员可以是静态数据.类成员总是实例成员,除非用static进行显示的声明. 事件是类的成员,在发生某些行 ...

  4. F08标准中Open命令的newunit选项

    从gfortran 4.5开始Open命令开始支持newunit选项,示例如下: integer :: u open(newunit=u, file="log.txt", posi ...

  5. ajax 提交所有表单内容及上传图片(文件),以及单独上传某个图片(文件)

    我以演示上传图片为例子: java代码如下(前端童鞋可以直接跳过看下面的html及js): package com.vatuu.web.action; import java.io.File; imp ...

  6. YTU 2391: 求素数

    2391: 求素数 时间限制: 1 Sec  内存限制: 128 MB 提交: 116  解决: 3 题目描述 设计一个程序,输出所有小于等于n(n为一个大于2的正整数)的素数. 要求:(1)每行输出 ...

  7. Ubuntu:Could not get lock /var/lib/dpkg/lock

    在ubuntu上使用apt-get时,碰过如下问题: 看意思是上一次使用apt-get时异常退出了,锁住了,google了下解决方案如下: 1.先判断是否有apt-get进程在跑,同一时刻只能有一个a ...

  8. CodeForces-380C:Sereja and Brackets(线段树与括号序列)

    Sereja has a bracket sequence s1, s2, ..., sn, or, in other words, a string s of length n, consistin ...

  9. 【USACO06NOV】路障

    [题目链接] 点击打开链接 [算法] 最短路 [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 5000 #de ...

  10. 51Nod 1327 棋盘游戏 —— 延迟DP

    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1327 看博客:https://www.cnblogs.com/Na ...