求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度。

我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可。因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的

要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算

不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码

我之前敲代码的时候还想起在线段树里面的覆盖要涉及懒惰标记(因为是对区间进行覆盖嘛,没向子走)和向上更新。。。不过想了一下不用,这个线段树不是普通那种,因为总是先覆盖底边,然后由等长的上边来解除覆盖,所以区间总是相对不变的,没必要进行向上或者向下更新

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid,r
using namespace std;
const int N=10010;
struct node
{
int lx,ly,hx,hy;
}rec[N];
struct node2
{
int l,r,h,f;
bool operator <(const node2& rhs) const{
if (h==rhs.h){
return f>rhs.f;
}
else return h<rhs.h;
}
}seg[N*2];
int X[N*2];
int n;
int flag[N<<2];
int d[N<<2];
void build(int rt,int l,int r)
{
flag[rt]=0;
d[rt]=0;
if (r-l<=1) return;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
void up(int rt,int l,int r)
{
if (flag[rt]>0){
d[rt]=X[r]-X[l];
}
else
{
if (r-l<=1) d[rt]=0;
else d[rt]=d[rt<<1]+d[rt<<1|1];
}
}
void cover(int L,int R,int v,int rt,int l,int r)
{
if (L<=l && r<=R)
{
flag[rt]+=v;
up(rt,l,r);
return;
}
if (r-l<=1) return ;
int mid=(l+r)>>1;
if (R<=mid) cover(L,R,v,lson);
else
if (L>mid) cover(L,R,v,rson);
else
{
cover(L,R,v,lson);
cover(L,R,v,rson);
}
up(rt,l,r);
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
int cnt=0;
for (int i=0;i<n;i++){
scanf("%d%d%d%d",&rec[i].lx,&rec[i].ly,&rec[i].hx,&rec[i].hy);
X[++cnt]=rec[i].lx;
seg[cnt].l=rec[i].lx;
seg[cnt].r=rec[i].hx;
seg[cnt].h=rec[i].ly;
seg[cnt].f=1; X[++cnt]=rec[i].hx;
seg[cnt].l=rec[i].lx;
seg[cnt].r=rec[i].hx;
seg[cnt].h=rec[i].hy;
seg[cnt].f=-1;
}
int m=1;
sort(X+1,X+1+cnt);
sort(seg+1,seg+1+cnt);
for(int i=2;i<=cnt;i++){
if (X[i]!=X[i-1]){
X[++m]=X[i];
}
}
int ans=0;
build(1,1,m);
//for (int i=1;i<=m;i++) cout<<X[i]<<endl;
for (int i=1;i<=cnt;i++){
//cout<<seg[i].l<<" "<<seg[i].r<<" "<<seg[i].f<<endl;
int l=lower_bound(X+1,X+1+m,seg[i].l)-X;
int r=lower_bound(X+1,X+1+m,seg[i].r)-X;
int tmp=d[1];
//cout<<X[l]<<" xxx "<<X[r]<<endl;
// cout<<"bf: "<<d[1]<<endl;
cover(l,r,seg[i].f,1,1,m);
tmp=d[1]-tmp;
if (tmp<0) tmp=-tmp;
//cout<<"af: "<<d[1]<<endl;
//cout<<tmp<<endl;
ans+=tmp;
}
//cout<<ans<<endl;
cnt=0;
for (int i=0;i<n;i++){
X[++cnt]=rec[i].ly;
seg[cnt].l=rec[i].ly;
seg[cnt].r=rec[i].hy;
seg[cnt].h=rec[i].lx;
seg[cnt].f=1; X[++cnt]=rec[i].hy;
seg[cnt].l=rec[i].ly;
seg[cnt].r=rec[i].hy;
seg[cnt].h=rec[i].hx;
seg[cnt].f=-1;
}
sort(X+1,X+1+cnt);
sort(seg+1,seg+1+cnt);
m=1;
for (int i=2;i<=cnt;i++){
if (X[i]!=X[i-1]){
X[++m]=X[i];
}
}
build(1,1,m);
for (int i=1;i<=cnt;i++){
int l=lower_bound(X+1,X+1+m,seg[i].l)-X;
int r=lower_bound(X+1,X+1+m,seg[i].r)-X;
int tmp=d[1];
cover(l,r,seg[i].f,1,1,m);
tmp=d[1]-tmp;
if (tmp<0) tmp=-tmp;
ans+=tmp;
}
printf("%d\n",ans);
}
return 0;
}
/*
2
0 0 5 2
2 -2 4 3
*/

  

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算的更多相关文章

  1. hdu 1828 Picture(线段树 || 普通hash标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others)    Mem ...

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

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

  3. HDU 1828 Picture (线段树+扫描线)(周长并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 给你n个矩形,让你求出总的周长. 类似面积并,面积并是扫描一次,周长并是扫描了两次,x轴一次,y ...

  4. hdu 1828 Picture(线段树轮廓线)

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  5. HDU 1828 Picture (线段树:扫描线周长)

    依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长. 容易发现,扫描线中的某一条横边对答案的贡献. 其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值 然后横着竖 ...

  6. POJ1177 Picture 线段树+离散化+扫描线

    求最终的覆盖图形周长,写这种代码应该短而精确,差的比较远 /* Problem: 1177 User: 96655 Memory: 348K Time: 32MS Language: C++ Resu ...

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

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

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

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

  9. POJ 2528 Mayor's posters(线段树+离散化)

    Mayor's posters 转载自:http://blog.csdn.net/winddreams/article/details/38443761 [题目链接]Mayor's posters [ ...

随机推荐

  1. python中if语句和循环语句

    //2019.12.05 python循环控制结构(一)控制循环结构 1-1 程序的判断语句与组合1.对于python的控制结构主要有以下三大类:(1)分支结构(2)循环结构(3)异常处理 2.pyt ...

  2. JS实现深拷贝,浅拷贝的方法

    在 JS 中,函数和对象都是浅拷贝(地址引用):其他的,例如布尔值.数字等基础数据类型都是深拷贝(值引用). 深拷贝 JSON.parse(JSON.stringify(src)):这种方法有局限性, ...

  3. 记一次关于NVROM中遇到的“Could not prepare Boot variable:No space left on device”问题的解决历程

    注:关于我电脑遇到的问题,不是一两句话能够说清楚的.为了能够比较完整的呈现问题的某些细节,在这篇博客中我会添加许多问题发生的背景,如果当中有观点与您的三观不合,请立即停止阅读,及时止损. 注:此篇文章 ...

  4. python的init函数里参数的作用

    问题发现 一直有一个疑问,有时我们在继承时,在__init__函数会出现可变参数*arg或关键字参数**kw这样的参数,这些参数有什么用?如果有用,这些参数时如何传递?传递些什么? 注:如果你不知道什 ...

  5. SSH Secure Shell 编码设置-----支持中文

    参考:https://www.cnblogs.com/hupf/p/6920323.html #vi /etc/sysconfig/i18n 将内容改为 LANG="zh_CN.GB1803 ...

  6. HashMap1.8之节点删除分析

    HashMap之节点删除 大家一直关注的都是HashMap如何添加节点,当节点数量大于8的时候转化为红黑树,否则使用链表等等,但大家是否有看过删除节点的处理逻辑呢? 今天来看看HashMap删除节点的 ...

  7. 「AT1983 BBQ Hard」

    呦,来一次久违的BBQ吧! AT题...日本的题库质量一向很高 这题是有关组合数的DP... 前置芝士 快速计算组合数,具体还是自行百度. 膜域下的除法. 具体做法 题目中的问题: \(\sum_{i ...

  8. 4专题总结-图论和DFS、BFS

    1图论: 1.1  133. Clone Graph https://leetcode.com/problems/clone-graph/#/description 思路:这题可以对照拷贝随机链表那道 ...

  9. 「CF55D」Beautiful numbers

    传送门 Luogu 解题思路 毒瘤数位DP,发现一个前缀我们只需要记录它对 \(\operatorname{lcm}(1,2,3,\cdots,9)=2520\) 取模的值即可,所以我们在 DP 时记 ...

  10. jumpserver手动配置文档

    1.环境  centos7.6   硬盘 200G  cpu  8核心  内存 32G (本地测试的时候,有报错,原因为虚拟机配置不够,此时为在pve虚拟化上面做的linux系统) 2.https:/ ...