http://poj.org/problem?id=1177
给若干矩形,求被覆盖的区域的周长。

将 y 坐标离散化后,按 x 坐标进行扫描。用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 cnt 。 前一个用来计算竖直方向的周长部分,后一个用来计算水平方向的。
用 left[node] 和 right[node] 来记录每个结点左端和右端是否被覆盖,用来维护 cnt

重叠的边也不能计算,这反应在对扫描线的排序上,两线重叠时入边应在出边之前。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;#define CHD int lc = node<<1,rc = node<<1|1;
#define MID int mid = (L+R)>>1;
#define debug(x) cout<<"debug "<<x<<endl;
#define rep(i,f,t) for(int i = (f),_end =(t); i <= _end; ++i)struct Node{int x;int y1,y2;int flag; //入边为1,出边为-1Node(int x,int y1,int y2,int f):x(x),y1(y1),y2(y2),flag(f){}bool operator< (const Node &n2)const{if(x == n2.x)return flag > n2.flag;//入边在出边前return x < n2.x;}
};
vector<Node> line;
vector<int> vs;
const int maxn = 10005;struct sgt{int len[maxn<<2];int cnt[maxn<<2];int cov[maxn<<2];int left[maxn<<2];int right[maxn<<2];void maintain(int node,int L,int R){if(cov[node] > 0){len[node] = vs[R]-vs[L-1];cnt[node] = 1;left[node] = right[node] = 1;} else {if(L == R){len[node] = 0;cnt[node] = 0;left[node] = right[node] = 0;}else{CHD;len[node] = len[lc]+len[rc];cnt[node] = cnt[lc]+cnt[rc]-(left[rc]&right[lc]);left[node] = left[lc];right[node] = right[rc];}}}void update(int from,int to,int val,int node,int L,int R){if(from <= L && R <= to){cov[node] += val;} else {MID;CHD;if(from <= mid) update(from,to,val,lc,L,mid);else    maintain(lc,L,mid);if(to > mid) update(from,to,val,rc,mid+1,R);else    maintain(rc,mid+1,R);}maintain(node,L,R);}int solve(){int ans = 0,ans2 = 0;//竖直和水平方向的周长int n = vs.size()-1;int last = 0;rep(i,0,line.size()-1){int x = line[i].x;int f = line[i].y1+1;int t = line[i].y2;if(i > 0){int tmp = cnt[1] * (x-line[i-1].x);ans2 += tmp*2;}update(f,t,line[i].flag,1,1,n);ans += abs(last-len[1]);//竖直方向长度变化last = len[1];}return ans+ans2;}
}tree;void pre(){sort(vs.begin(),vs.end());vs.erase(unique(vs.begin(),vs.end()),vs.end());rep(i,0,line.size()-1){line[i].y1 = lower_bound(vs.begin(),vs.end(),line[i].y1) - vs.begin();line[i].y2 = lower_bound(vs.begin(),vs.end(),line[i].y2) - vs.begin();}sort(line.begin(),line.end());
}int main(){int n;scanf("%d",&n);if(n == 0){printf("0\n");return 0;}line.reserve(n<<1);vs.reserve(n<<1);rep(i,1,n){int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);vs.push_back(y1);vs.push_back(y2);line.push_back(Node(x1,y1,y2,1));line.push_back(Node(x2,y1,y2,-1));}pre();int ans = tree.solve();printf("%d\n",ans);return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/DSChan/p/4861973.html

POJ 1177 Picture [离散化+扫描线+线段树]相关推荐

  1. hdu 4419 Colourful Rectangle (离散化扫描线线段树)

    Problem - 4419 题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小. 比较明显,这题要从矩形面积并的方向出发.如果做过矩形面积并的题,用线段树 ...

  2. HDU 1828:Picture(扫描线+线段树 矩形周长并)

    题目链接 题意 给出n个矩形,求周长并. 思路 学了区间并,比较容易想到周长并. 我是对x方向和y方向分别做两次扫描线.应该记录一个pre变量,记录上一次扫描的时候的长度,对于每次遇到扫描线统计答案的 ...

  3. POJ 1151 扫描线 线段树

    题意:给定平面直角坐标系中的N个矩形,求它们的面积并. 题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序.记录所有的y坐标以后排序离散化.离 ...

  4. 【HDU5091】Beam Cannon,扫描线+线段树

    传送门 思路: 扫描线的经典问题 然而并不是很会做-- 对x坐标差分一下(例如(x,y)类型为1,(x+w,y)的类型就是-1,以便于之后扫描可以去除该点),然后对y坐标转化为正数(便于操作为线段树上 ...

  5. 扫描线+线段树简介 AcWing 248窗内的星星题解

    ----出自南昌理工学院ACM集训队 这周学习了线段树和扫描线的解题方法,下面由小菜鸡简介一下: 一般扫描线的题目最简单的便是扫描线裸模板(一般来说的话:数据范围小),其次的话便是进行拓展成线段树+扫 ...

  6. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  7. poj 2528 Mayor's posters (线段树+离散化)

    /*离散化+线段树由于 数据的输入最大是 10000000 ,直接用开数组肯点会超,所以要将起离散话,首先 ,我们存储输入的边,将其离散化,后面的就和一般的线段树一样可. */#include< ...

  8. [矩形并-扫描线-线段树]Picture

    最近在补数学和几何,没啥好写的,因为已经决定每天至少写一篇了,今天随便拿个题水水. 题目大意:给你N个边平行于坐标轴的矩形,求它们并的周长.(N<=5000) 思路:这个数据范围瞎暴力就过了,但 ...

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

    还是做了线段树的题目,玩了两天也要继续看看题目了.之前就有看离散化的概念,大家可以去百度百科一下,简单转载一个例子 离散化 的大概思路 : 比如说给你一组 数据 1 4 1000 100000, 如果 ...

最新文章

  1. C++实现8皇后问题
  2. golang 获取路径 文件名 后缀
  3. python中def fun(a、b=200)_python中的函数的参数和可变参数
  4. oracle operation_type,oracle静默安装
  5. lazyload 加载
  6. python文件行数运行结果_python统计文件行数
  7. 【笔记】《C#高效编程改进C#代码的50个行之有效的办法》第1章C#语言习惯(1)--属性的特性以及索引器(SamWang)...
  8. 彻底杜绝warning: Cannot add header information - headers already sent in......
  9. poj 2387 Til the Cows Come Home spfa基础题,入门,我的第一个
  10. Linux root找回密码的方法
  11. 手写Spring框架
  12. myql GROU_CONCAT 与FIND_IN_SET查询结果为空问题解决
  13. MIPI DSI CLK计算
  14. 趋势性、季节性、周期性
  15. Android Studio中虚拟机运行时报错的解决方法
  16. EXCEL的查找:如何按 行号+列号 进行查询, 可用indirect() + match() 或 index() + match()
  17. 构建基于Linux平台的开源×××服务器
  18. redission使用案例
  19. 百度网盘是如何实现妙传的
  20. edius制作视频音画不同步原因

热门文章

  1. innodb主键的长度为什么不能大于767字节
  2. python【力扣LeetCode算法题库】42-接雨水(双指针法)
  3. 织梦html不能生成,内容预览及生成HTML
  4. 原创不易!做网络推广怎么才能更好地保护网站的原创文章?
  5. 网络推广——网络推广专员是如何进行图像优化的?
  6. 外链对网站SEO优化起什么作用?
  7. 网站主题明确需注意这三项原则!
  8. 网站建设之前需要先了解目标受众
  9. 苹果8a1660是什么版本_iOS 13频繁“翻车”,果粉们面对苹果将情何以堪
  10. python数据分析numpy_利用python进行数据分析-NumPy高级应用