Poj--1177(线段树,扫描线,轮廓周长)

2014-09-25 01:41:49

思路:基本思路和p1151差不多,首先把线段分成平行于x轴和平行于y轴的两组,分别考虑。注意把每个点的x,y坐标加10001,因为线段树节点下标不能为负和0,(当然用离散化做就不用这样处理了),每加进来一条线段,就对相应的线段cover值加1,然后求出当前已经被覆盖的区间的总长度L,然后:把这次求出的 L 和上一次求出的 L’ 作差取绝对值,就得到了因为加入当前线段而新增的周长。就这样逐个计算累加,即得答案。

  自己YY水过。。。QAQ

  1 /*************************************************************************
  2     > File Name: p1177.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Wed 24 Sep 2014 10:39:20 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <queue>
 14 #include <iostream>
 15 #include <algorithm>
 16 using namespace std;
 17 typedef long long ll;
 18 const int INF = 1 << 29;
 19 const int maxn = 10010;
 20 const int RA = 20000;
 21 
 22 struct Edge{
 23     int st,p1,p2,flag;
 24     inline friend bool operator < (Edge a,Edge b){
 25         return a.st < b.st;
 26     }
 27 }ey[maxn],ex[maxn];
 28 
 29 struct node{
 30     int l,r;
 31     int cover,len;
 32 }a[maxn << 4];
 33 
 34 int n;
 35 int y[maxn],x[maxn];
 36 
 37 void Build_tree(int pos,int l,int r){
 38     a[pos].l = l;
 39     a[pos].r = r;
 40     a[pos].cover = a[pos].len = 0;
 41     if(l + 1 == r)
 42         return;
 43     int mid = l + (r - l) / 2;
 44     Build_tree(pos << 1,l,mid);
 45     Build_tree(pos << 1 | 1,mid,r);
 46 }
 47 
 48 void Cal_len(int pos){
 49     if(a[pos].cover >= 1)
 50         a[pos].len = a[pos].r - a[pos].l;
 51     else if(a[pos].l + 1 == a[pos].r)
 52         a[pos].len = 0;
 53     else
 54         a[pos].len = a[pos << 1].len + a[pos << 1 | 1].len;
 55 }
 56 
 57 void Update(int pos,int l,int r,Edge t){
 58     if(a[pos].l == t.p1 && a[pos].r == t.p2){
 59         a[pos].cover += t.flag;
 60         Cal_len(pos);
 61         return;
 62     }
 63     int mid = l + (r - l) / 2;
 64     if(t.p2 <= mid) Update(pos << 1,l,mid,t);
 65     else if(t.p1 >= mid) Update(pos << 1 | 1,mid,r,t);
 66     else{
 67         Edge tmp = t;
 68         tmp.p2 = mid;
 69         Update(pos << 1,l,mid,tmp);
 70         tmp.p2 = t.p2;
 71         tmp.p1 = mid;
 72         Update(pos << 1 | 1,mid,r,tmp);
 73     }
 74     Cal_len(pos);
 75 }
 76 
 77 int main(){
 78     //freopen("in","r",stdin);
 79     int x1,y1,x2,y2,c = 0;
 80     scanf("%d",&n);
 81     for(int i = 1; i <= n; ++i){
 82         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
 83         x1 += 10001;
 84         y1 += 10001;
 85         x2 += 10001;
 86         y2 += 10001;
 87 
 88         ey[++c].st = x1;
 89         ey[c].p1 = y1;
 90         ey[c].p2 = y2;
 91         ey[c].flag = 1;
 92         y[c] = y1;
 93         ex[c].st = y1;
 94         ex[c].p1 = x1;
 95         ex[c].p2 = x2;
 96         ex[c].flag = 1;
 97         x[c] = x1;
 98 
 99         ey[++c].st = x2;
100         ey[c].p1 = y1;
101         ey[c].p2 = y2;
102         ey[c].flag = -1;
103         y[c] = y2;
104         ex[c].st = y2;
105         ex[c].p1 = x1;
106         ex[c].p2 = x2;
107         ex[c].flag = -1;
108         x[c] = x2;
109     }
110     sort(ey + 1,ey + c + 1);
111     sort(ex + 1,ex + c + 1);
112     sort(y + 1,y + c + 1);
113     sort(x + 1,x + c + 1);
114     int wide = 0,high = 0,pre = 0;
115     Build_tree(1,1,RA);
116     for(int i = 1; i <= c; ++i){
117         Update(1,1,RA,ey[i]);
118         wide += abs(a[1].len - pre);
119         pre = a[1].len;
120     }
121     Build_tree(1,1,RA);
122     pre = 0;
123     for(int i = 1; i <= c; ++i){
124         Update(1,1,RA,ex[i]);
125         high += abs(a[1].len - pre);
126         pre = a[1].len;
127     }
128     printf("%d\n",wide + high);
129     return 0;
130 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/3991944.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值