hdu 1828 线段树扫描线(周长)
来源:互联网 发布:如何打开oracle数据库 编辑:程序博客网 时间:2024/06/06 00:01
Picture
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3897 Accepted Submission(s): 1978
Problem Description
A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter.
Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.
The corresponding boundary is the whole set of line segments drawn in Figure 2.
The vertices of all rectangles have integer coordinates.
Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.
The corresponding boundary is the whole set of line segments drawn in Figure 2.
The vertices of all rectangles have integer coordinates.
Input
Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.
0 <= number of rectangles < 5000
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.
Please process to the end of file.
0 <= number of rectangles < 5000
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.
Please process to the end of file.
Output
Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.
Sample Input
7-15 0 5 10-5 8 20 2515 -4 24 140 -6 16 42 15 10 2230 10 36 2034 0 40 16
Sample Output
228
First
/*hdu 1828 线段树扫描线(周长)给你一些矩阵,有部分or全部重叠.求最终图形的周长对于x轴的边,矩阵的下边标为1,矩阵的上边标为-1.每次插入后用当前覆盖面积减去上一次的覆盖面积(即新增长度),扫描过一个矩阵的上边后便能消除下边的影响。对x,y轴分别扫描一次即可最开始没考虑重边的问题,结果C++ AC(G++ WR)然后更改后G++才过 - -20 0 1 11 0 2 120 0 1 10 1 1 2hhh-2016-03-26 16:35:21*/#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <functional>using namespace std;#define lson (i<<1)#define rson ((i<<1)|1)typedef long long ll;const int maxn = 20050;int a[maxn];struct node{ int l,r; int sum,len; int mid() { return (l+r)>>1; }} tree[maxn*5];void push_up(int i){ if(tree[i].sum) tree[i].len = (tree[i].r-tree[i].l+1); else if(tree[i].l == tree[i].r) tree[i].len = 0; else tree[i].len = tree[lson].len+tree[rson].len;}void build(int i,int l,int r){ tree[i].l = l; tree[i].r = r; tree[i].sum = 0; tree[i].len = 0; if(l == r) return ; int mid = tree[i].mid(); build(lson,l,mid); build(rson,mid+1,r); push_up(i);}void push_down(int i){// if(tree[i].sum)// {// tree[lson].sum += tree[i].sum;// tree[rson].sum += tree[i].sum;// tree[lson].len = tree[lson].r-tree[lson].l;// tree[rson].len = tree[rson].r-tree[rson].l;// }}void Insert(int i,int l,int r,int val){ if(tree[i].l >= l && tree[i].r <=r ) { tree[i].sum += val; push_up(i); return ; } int mid = tree[i].mid(); push_down(i); if(l <= mid) Insert(lson,l,r,val); if(r > mid) Insert(rson,l,r,val); push_up(i);}struct edge{ int l,r; int va,high;};edge tx[maxn*2];edge ty[maxn*2];bool cmp(edge a,edge b){ if(a.high != b.high) return a.high < b.high; else //如果有重边则要先插入在删除 return a.va > b.va;}int main(){ int n; while(scanf("%d",&n) != EOF) { int x1,x2,y1,y2; int tox = 0,lx=0x3f3f3f3f,rx=0; int toy = 0,ly=0x3f3f3f3f,ry=0; for(int i = 1; i <= n; i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); lx = min(x1,lx),rx = max(rx,x2); ly = min(y1,ly),ry = max(ry,y2); tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1; tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1; ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x1,ty[toy++].va=1; ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x2,ty[toy++].va=-1; } sort(tx,tx+tox,cmp); sort(ty,ty+toy,cmp); int ans=0,prelen = 0; build(1,lx,rx-1); for(int i = 0; i < tox; i++) { Insert(1,tx[i].l,tx[i].r-1,tx[i].va); ans += abs(tree[1].len-prelen); prelen = tree[1].len; } //cout << ans <<endl; build(1,ly,ry-1); prelen = 0; for(int i = 0; i < toy; i++) { Insert(1,ty[i].l,ty[i].r-1,ty[i].va); ans += abs(tree[1].len-prelen); prelen = tree[1].len; } cout << ans <<endl; } return 0;}
Second
/*hdu 1828 线段树扫描(周长)2在向上扫描的过程中我们可以计算出平行于x轴的长度然后在两条线之间我们只需要计算出有多少条竖线便能得带这两条线之间平行于y轴的长度。用ls和rs来表示当前节点左右端点是否被覆盖在处理竖线数量时,注意合并带来的影响,假设lson.rs和rson.ls都存在值的话说明存在重叠的部分hhh-2016-03-26 17:58:50*/#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <functional>using namespace std;#define lson (i<<1)#define rson ((i<<1)|1)typedef long long ll;const int maxn = 20050;int a[maxn];struct node{ int l,r; int sum,len; int num,ls,rs; int mid() { return (l+r)>>1; }} tree[maxn*5];void push_up(int i){ if(tree[i].sum) { tree[i].len = (tree[i].r-tree[i].l+1); tree[i].ls = tree[i].rs = 1; tree[i].num = 1; } else if(tree[i].l == tree[i].r) { tree[i].len= 0; tree[i].num=tree[i].rs=tree[i].ls=0; } else { tree[i].len = tree[lson].len+tree[rson].len; tree[i].ls = tree[lson].ls; tree[i].rs = tree[rson].rs; tree[i].num = tree[lson].num+tree[rson].num; tree[i].num -= (tree[lson].rs&tree[rson].ls); //减去重叠的部分 }}void build(int i,int l,int r){ tree[i].l = l; tree[i].r = r; tree[i].sum = tree[i].len = 0; tree[i].ls = tree[i].rs = tree[i].num = 0; if(l == r) return ; int mid = tree[i].mid(); build(lson,l,mid); build(rson,mid+1,r); push_up(i);}void push_down(int i){}void Insert(int i,int l,int r,int val){ if(tree[i].l >= l && tree[i].r <=r ) { tree[i].sum += val; push_up(i); return ; } int mid = tree[i].mid(); push_down(i); if(l <= mid) Insert(lson,l,r,val); if(r > mid) Insert(rson,l,r,val); push_up(i);}struct edge{ int l,r; int va,high,id;};edge tx[maxn*2];bool cmp(edge a,edge b){ if(a.high != b.high) return a.high < b.high; else return a.va > b.va;}int main(){ int n; while(scanf("%d",&n) != EOF) { int x1,x2,y1,y2; int tox = 0,lx=0x3f3f3f3f,rx=0; for(int i = 1; i <= n; i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); lx = min(x1,lx),rx = max(rx,x2); tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1; tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1; } sort(tx,tx+tox,cmp); int ans=0,prelen = 0; build(1,lx,rx-1); //tx[tox] = tx[tox+1]; for(int i = 0; i < tox; i++) { Insert(1,tx[i].l,tx[i].r-1,tx[i].va); ans += abs(tree[1].len-prelen); if(i != tox-1) ans += (tx[i+1].high-tx[i].high)*tree[1].num*2; prelen = tree[1].len; } cout << ans <<endl; } return 0;}
0 0
- hdu 1828 线段树扫描线(周长)
- hdu 1828线段树扫描线求周长并
- hdu 1828 Picture(线段树&扫描线&周长并)
- HDU 1828 线段树之扫描线之周长并
- hdu 1828、poj1177求矩形周长并 线段树 扫描线
- hdu 1828 Picture(线段树扫描线矩形周长并)
- HDU 1828——Picture(线段树+周长并+扫描线)
- 线段树扫描线(矩阵周长并)——HDU 1828
- poj 1177 || HDU 1828 Picture (线段树扫描线求 图形并的周长)
- HDU 1828 Picture(线段树扫描线·周长并)
- HDU 1828 Picture (线段树扫描线求周长并 区间合并)
- hdu 1828 Picture(线段树,扫描线之周长并)
- hdu 1542 矩形面积并 &&hdu 1255 矩形面积交 && hdu 1828 矩阵周长并 线段树+扫描线入门
- 线段树扫描线(周长并)hdu1828
- hdu1828线段树扫描线求周长
- 【线段树 && 扫描线 && 周长】POJ
- 算法总结:【线段树+扫描线】&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828)
- HDU 1828 Picture 扫描线 求周长
- LeetCode Algorithms #66 <Pascal's Triangle>
- EasyUi Datagrid的基础使用
- window系统bat方式启动tomcat出现java.lang.OutOfmemoryError:PermGen Space 错误
- 剑指offer面试题 求数字在数组中出现的次数
- Tarjan三大算法之双连通分量(割点,桥)
- hdu 1828 线段树扫描线(周长)
- 设计模式-工厂设计模式读感
- 重学数据结构系列之——森林之并查集(Disjoint set)
- spark访问redis集群中某个数据库的问题
- TCP/IP
- ubuntu系统安装Matlab2014a
- 【matlab】:颜色模型的分类及颜色模型的转换简介
- 解决Android Studio添加依赖时出现“Manifest merger failed”错误
- IA32架构CPUID、RDTSC指令与CPU测速