hdu 1828 Picture(矩形周长并)
来源:互联网 发布:cf一键领枪软件 编辑:程序博客网 时间:2024/05/16 15:46
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1828
题目大意:就是给你n个矩形,每个矩形由左上和右上两个点确定,问你他们的周长并是多少?
思路:线段树+扫描线。同样需要左闭右开处理,稍微和面积并有点不同,底线的长度求法和面积并一样,关键是还要-上次的底线长度,求这个值abs,然后这就是
update当前这条line之后新增的横的长度。然后就是求竖的那种线有几根的问题,如果某个区间被某几条线完全覆盖,那么我们就设它的
竖线有两根,然后在定义两个数组 lbd,rbd,表示这个区间的左右端点存不存在竖线(因为是左闭右开,右端点是-1的,其实是l、r+1 存不存在竖线),
push_up的时候,如果左儿子的rbd存在,右儿子的lbd存在,就要 两个numseg值加起来-2,因为这两条线重合了。具体的可以看代码里的 push_up,我感觉
那里是关键。
代码是直接从面积那里并改过来的。
题目大意:就是给你n个矩形,每个矩形由左上和右上两个点确定,问你他们的周长并是多少?
思路:线段树+扫描线。同样需要左闭右开处理,稍微和面积并有点不同,底线的长度求法和面积并一样,关键是还要-上次的底线长度,求这个值abs,然后这就是
update当前这条line之后新增的横的长度。然后就是求竖的那种线有几根的问题,如果某个区间被某几条线完全覆盖,那么我们就设它的
竖线有两根,然后在定义两个数组 lbd,rbd,表示这个区间的左右端点存不存在竖线(因为是左闭右开,右端点是-1的,其实是l、r+1 存不存在竖线),
push_up的时候,如果左儿子的rbd存在,右儿子的lbd存在,就要 两个numseg值加起来-2,因为这两条线重合了。具体的可以看代码里的 push_up,我感觉
那里是关键。
代码是直接从面积那里并改过来的。
代码如下:
#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define lson rt<<1,l,mid#define rson rt<<1|1,mid+1,rconst int MAXN = 5005<<1;struct Line{ int l,r,h; int flag; Line(){} Line(int a,int b,int c,int d) { l = a; r = b; h = c; flag = d; } bool operator < (const Line &tmp) const { return h < tmp.h; }} line[MAXN];int x[MAXN];int Bin(int l,int r,int key){ while(l <= r) { int mid = (l+r)>>1; if(x[mid] == key) { return mid; } else if(x[mid] < key) l = mid+1; else r = mid-1; } return -1;}int sum[MAXN<<2],cnt[MAXN<<2],numseg[MAXN<<2],lbd[MAXN<<2],rbd[MAXN<<2];void push_up(int rt,int l,int r){ if(cnt[rt]) { sum[rt] = x[r+1]-x[l]; numseg[rt] = 2; lbd[rt] = rbd[rt] = 1; } else if(l == r) sum[rt] = numseg[rt] = lbd[rt] = rbd[rt] = 0; else { sum[rt] = sum[rt<<1]+sum[rt<<1|1]; numseg[rt] = numseg[rt<<1]+numseg[rt<<1|1]; if(lbd[rt<<1|1] && rbd[rt<<1]) numseg[rt] -= 2; lbd[rt] = lbd[rt<<1]; rbd[rt] = rbd[rt<<1|1]; }}void update(int rt,int l,int r,int a,int b,int c){ if(a <= l && b >= r) { cnt[rt] += c; push_up(rt,l,r); return ; } int mid = l+r>>1; if(a <= mid) update(lson,a,b,c); if(b > mid) update(rson,a,b,c); push_up(rt,l,r);}void build(int rt,int l,int r){ cnt[rt] = sum[rt] = numseg[rt] = lbd[rt] = rbd[rt] = 0; if(l == r) return ; int mid = l+r>>1; build(lson); build(rson);}int main(){ int n; while(~scanf("%d",&n)) { int a,b,c,d; int tot = 0; for(int i = 0;i < n;i++) { scanf("%d%d%d%d",&a,&b,&c,&d); x[tot] = a; line[tot++] = Line(a,c,b,1); x[tot] = c; line[tot++] = Line(a,c,d,-1); } sort(x,x+tot); sort(line,line+tot); int m = unique(x,x+tot)-x; build(1,0,m-1); int ans = 0; int last = 0; for(int i = 0;i < tot;i++) { int l = Bin(0,m-1,line[i].l); int r = Bin(0,m-1,line[i].r); if(l >= r) continue; //printf("l = %d,r = %d,m = %d\n",l,r,m); update(1,0,m-1,l,r-1,line[i].flag); ans += numseg[1]*(i == tot-1 ? 0 : (line[i+1].h-line[i].h)); ans += abs(sum[1]-last); last = sum[1]; //printf("%d,%d,ans = %d\n",numseg[1],sum[1],ans); } printf("%d\n",ans); } return 0;}/*210 10 20 2015 15 25 25*/
- hdu 1828 Picture(矩形周长并)
- HDU 1828 Picture(矩形周长并)
- 矩形周长并 hdu 1828 Picture
- HDOJ-1828 Picture(矩形周长并)
- poj 1177 / hdu 1828 Picture 矩形周长并
- Hdu 1828 Picture 线段树+矩形周长并
- 矩形周长并 poj 1177Picture/hdu 1828
- hdu 1828 Picture 线段树 矩形周长并
- hdu 1828 Picture(线段树扫描线矩形周长并)
- HDU 1828 Picture(矩形周长的并+扫描线+离散化)
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
- HDU - 1828 Picture (线段树求并周长)
- HDU 1828 Picture(线段树的周长并)
- poj 1177 Picture(线段树求矩形周长并)
- hdu1828 Picture(扫描线+矩形周长并+线段树)
- POJ 1177 Picture(矩形并的周长)
- hdu1828 Picture (矩形周长并+扫描线)
- POJ 1177 Picture 矩形周长并
- JBoss Twiddle
- 获取加载素材的进度
- 路基箱的作用
- hdu 1542 Atlantis(矩形面积并)
- ndroid appwidget 一些用法和注意事项
- hdu 1828 Picture(矩形周长并)
- hdu 1255 覆盖的面积(矩形面积二次交)
- sql 多行列转换( case & union all)
- SQL Server数据库事务日志序列号(LSN)介绍
- poj 3670 Eating Together(最长不下降子序列、LIS)
- ios的一些基本知识
- 【括号配对问题 2】
- 杭电1080-Lcs+DP(**有借鉴**)
- 索引建立步骤