参考  https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html

#include <stdio.h>
#include <algorithm>
#define LEN 10000
using namespace std; struct Node
{
int left;
int right;
int count;//被覆盖次数
//所包含的区间数量,如三条[1,2],[2,3],[4,5]线段被覆盖,则line=2,因为 [1,2],[2,3]是连续的。
int line;//所包含的区间数量
int lbd;//左端点是否被覆盖 用来辅助对line的计算
int rbd;//右端点是否被覆盖
int m;//测度 ,即覆盖的区间长度,如[2,8]就为6
}node[LEN*];;
struct ScanLine
{
int x;
int y1;
int y2;
int flag;
}scan[LEN];;
int y[LEN];
void build(int l, int r, int i)
{
node[i].left = l;
node[i].right = r;
node[i].count = ;
node[i].m = ;
node[i].line = ;
if (r - l > )
{
int middle = (l + r)/;
build(l, middle, *i + );
build(middle, r, *i + );
}
}
//更新测度m
void update_m(int i)
{
if (node[i].count > )
node[i].m = y[node[i].right] - y[node[i].left];
else if (node[i].right - node[i].left == )
node[i].m = ;
else
{
node[i].m = node[*i + ].m + node[*i + ].m;
}
}
//更新line
void update_line(int i)
{
if (node[i].count > )
{
node[i].lbd = ;
node[i].rbd = ;
node[i].line = ;
}
else if (node[i].right - node[i].left == )
{
node[i].lbd = ;
node[i].rbd = ;
node[i].line = ;
}
else
{
node[i].lbd = node[*i + ].lbd;
node[i].rbd = node[*i + ].rbd;
node[i].line = node[*i + ].line + node[*i + ].line - node[*i + ].rbd*node[*i + ].lbd;
}
}
void insert(int l, int r, int i)
{
//在这里要取离散化之前的原值进行比较
if (y[node[i].left] >= l && y[node[i].right] <= r)
(node[i].count)++;
else if (node[i].right - node[i].left == )
return;
else
{
int middle = (node[i].left + node[i].right)/;
if (r <= y[middle])
insert(l, r, *i + );
else if (l >= y[middle])
insert(l, r, *i + );
else
{
insert(l, y[middle], *i + );
insert(y[middle], r, *i + );
}
}
update_m(i);
update_line(i);
} void remove(int l, int r, int i)
{
////在这里要取离散化之前的原值进行比较
if (y[node[i].left] >= l && y[node[i].right] <= r)
(node[i].count)--;
else if (node[i].right - node[i].left == )
return;
else
{
int middle = (node[i].left + node[i].right)/;
if (r <= y[middle])
remove(l, r, *i + );
else if (l >= y[middle])
remove(l, r, *i + );
else
{
remove(l, y[middle], *i + );
remove(y[middle], r, *i + );
}
}
update_m(i);
update_line(i);
} bool cmp(ScanLine line1,ScanLine line2)
{
if (line1.x == line2.x)
return line1.flag > line2.flag;
return (line1.x < line2.x);
} int main()
{
int n;
scanf("%d", &n);
int x1, y1, x2, y2;
int i = ;
while (n--)
{
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
scan[i].x = x1;
scan[i].y1 = y1;
scan[i].y2 = y2;
scan[i].flag = ;
y[i++] = y1;
scan[i].x = x2;
scan[i].y1 = y1;
scan[i].y2 = y2;
scan[i].flag = ;
y[i++] = y2;
}
sort(y, y + i);
sort(scan, scan + i, cmp);
//y数组中不重复的个数
int unique_count = unique(y, y + i) - y;
//离散化,建立线段树
build(, unique_count - , );
int perimeter = ;
int now_m = ;
int now_line = ;
for (int j = ; j < i; j++)
{
if (scan[j].flag)
insert(scan[j].y1, scan[j].y2, );
else
remove(scan[j].y1, scan[j].y2, );
if (j >= )
perimeter += *now_line*(scan[j].x - scan[j-].x);
//要减去,因为一个边只能算一次,要减去上一次已经算过的边
perimeter += abs(node[].m - now_m);
now_m = node[].m;
now_line = node[].line;
}
printf("%d\n", perimeter);
return ;
}

Picture POJ - 1177 线段树+离散化+扫描线 求交叉图像周长的更多相关文章

  1. 【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)

    [POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  2. hdu1542 矩形面积并(线段树+离散化+扫描线)

    题意: 给你n个矩形,输入每个矩形的左上角坐标和右下角坐标. 然后求矩形的总面积.(矩形可能相交). 题解: 前言: 先说说做这道题的感受: 刚看到这道题顿时就懵逼了,几何 烂的渣渣.后来从网上搜题解 ...

  3. POJ 1177 Picture(线段树:扫描线求轮廓周长)

    题目链接:http://poj.org/problem?id=1177 题目大意:若干个矩形,求这些矩形重叠形成的图形的轮廓周长. 解题思路:这里引用一下大牛的思路:kuangbin 总体思路: 1. ...

  4. POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

    求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...

  5. POJ 1151Atlantis 矩形面积并[线段树 离散化 扫描线]

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Descrip ...

  6. POJ - 1177 线段树

    POJ - 1177 扫描线 这道题也算是一道扫描线的经典题目了. 只不过这道题是算周长,非常有意思的一道题.我们已经知道了,一般求面积并,是如何求的,现在我们要把扫描线进行改造一下,使得能算周长. ...

  7. poj 2528(线段树+离散化) 市长的海报

    http://poj.org/problem?id=2528 题目大意是市长竞选要贴海报,给出墙的长度和依次张贴的海报的长度区间(参考题目给的图),问最后你能看见的海报有几张 就是有的先贴的海报可能会 ...

  8. POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Descrip ...

  9. poj 2528 线段树+离散化

    题意:在墙上贴一堆海报(只看横坐标,可以抽象成一线段),新海报可以覆盖旧海报.求最后能看到多少张海报 sol:线段树成段更新.铺第i张海报的时候更新sg[i].x~sg[i].y这一段为i. 然而坐标 ...

随机推荐

  1. yum管理及源码安装

    一.配置YUM库及更新操作 yum概述 基于RPM包构建的软件更新机制,自动解决软件依赖关系 YUM仓库格式 本地:file:// 网络:ftp://或http:// yum源里面包含的内容 .rpm ...

  2. 优雅地关闭worker进程

    关闭nginx两种方式 nginx -s stop  立即停止nginx进程  nginx -s quit 优雅地关闭worker进程 开始优雅的关闭worker进程后 01设置定时器 worker_ ...

  3. C指针右左法则

    摘录的别人的:  C语言所有复杂的指针声明,都是由各种声明嵌套构成的.如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法.不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出 ...

  4. jsp连接mysql案例

    下载mysql-connector-java-5.1.26 将mysql-connector-java-5.1.26-bin.jar放在\jdk\jre\lib\ext中 -------------- ...

  5. 提升命令行效率的Bash快捷键

    转自:http://linuxtoy.org/archives/bash-shortcuts.html 生活在 Bash shell 中,熟记以下快捷键,将极大的提高你的命令行操作效率. 大部分对其他 ...

  6. 渡一教育公开课重点笔记之css

    主流浏览器及内核 浏览器         内核 IE             trident Firefox    Gecko Google chrome    Webkit/blink(2014年上 ...

  7. javascript检测客户端环境是否是pc端

    //isPC(): 检测客户端环境是否是pc端 function isPC(){ let userAgent = navigator.userAgent; let agents = ["An ...

  8. ELF文件之三——使用链接脚本-2个函数

    main.c int main() { ; } int add() { ; } main.o的比较 与之二相比,section header offset由0x90变为0xA4,增加0x14,即add ...

  9. zabbix 自定义监控项报警给单独的人

    需求就是某个交换机的流量达到某个值后需要报警,但报警的内容不是发给所有的人,而是只发给特定的一个人,而其他的报警信息不能让他收到,他只能收到这一个报警项的报警 1:创建好用户定义好手机号 2:新增加一 ...

  10. HTTP 中 GET 与 POST 的区别(详解)

    我们都知道GET和POST是HTTP请求的两种基本方法,最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 很多权威网站总结出的他们的区别: GET在浏览器回退 ...