poj1177Picture(线段树-周长并)

链接

神奇的扫描线啊

估计之前刷面积并的时候太急了 没来得及理解 。。

有一大段代码是与面积并一模一样的 都是离散化 更新

面积并是扫描的x  这次也一样

因为周长只算外围的 所以扫描到一条x边时 要减去上一次扫描到的 对于Y方向上 就是与面积并不大一样的地方了

看篇带图的讲解吧 网上的题解都大同小异 估计出自一人之手

http://blog.sina.com.cn/s/blog_691ce2b7010177dz.html

它是扫描的Y  其实方法是一样的 横过来就是

对于我的代码 自己感觉不好理解在于求区间数

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 using namespace std;
  7 #define N 10010
  8 #define LL long long
  9 struct node
 10 {
 11     int lx,rx,y,d;
 12     node(){}
 13     node(int a,int b,int c,int d):lx(a),rx(b),y(c),d(d){}
 14     bool operator < (const node &S) const
 15     {
 16         if(y == S.y) return d > S.d;
 17         return y<S.y;
 18     }
 19 }mat[N];
 20 int que[N],sum[N<<2],lg[N<<2],rg[N<<2],seg[N<<2];
 21 int cnt[N<<2];
 22 LL ans=0;
 23 int bin(int k,int low,int high)
 24 {
 25     int m;
 26     while(low<=high)
 27     {
 28         m  = (low+high)/2;
 29         if(que[m]==k)
 30         return m;
 31         if(que[m]>k)
 32         high = m-1;
 33         else
 34         low = m+1;
 35     }
 36     return m;
 37 }
 38 void up(int l,int r,int w)
 39 {
 40     if(cnt[w])//入边就更新这段的值 及区间数 (1个区间 2条Y边)
 41     {
 42         sum[w] = que[r+1]-que[l];
 43         seg[w] = 2;
 44         lg[w] = 1;
 45         rg[w] = 1;
 46     }
 47     else if(l==r)
 48     {
 49         sum[w] = seg[w] = lg[w] = rg[w] = 0;//出边的话 消除这条边
 50     }
 51     else//非出入边 向上更新 与平常线段树一样 等于子孩子相加
 52     {
 53         sum[w] = sum[w<<1]+sum[w<<1|1];
 54         seg[w] = seg[w<<1]+seg[w<<1|1];
 55         lg[w] = lg[w<<1];
 56         rg[w] = rg[w<<1|1];
 57         if(lg[w<<1|1]&&rg[w<<1])//左右相连 减去重复的
 58         seg[w]-=2;
 59     }
 60 }
 61 void update(int a,int b,int d,int l,int r,int w)
 62 {
 63     if(a<=l&&b>=r)
 64     {
 65         cnt[w]+=d;
 66         up(l,r,w);
 67         return ;
 68     }
 69     int m = (l+r)>>1;
 70     if(a<=m)
 71     update(a,b,d,l,m,w<<1);
 72     if(b>m)
 73     update(a,b,d,m+1,r,w<<1|1);
 74     up(l,r,w);
 75 }
 76 int main()
 77 {
 78     int i,n,a,b,c,d;
 79     while(scanf("%d",&n)!=EOF)
 80     {
 81         int num=0;
 82         for(i = 1; i <= n ; i++)
 83         {
 84             scanf("%d%d%d%d",&a,&b,&c,&d);
 85             que[num] = a;
 86             mat[num++] = node(a,c,b,1);
 87             que[num] = c;
 88             mat[num++] = node(a,c,d,-1);
 89         }
 90         sort(que,que+num);
 91         sort(mat,mat+num);
 92         int k = 1;
 93         for(i = 1 ; i < num ; i++)
 94         {
 95             if(que[i]!=que[i-1])
 96             que[k++] = que[i];
 97         }
 98         memset(cnt,0,sizeof(cnt));
 99         memset(sum,0,sizeof(sum));
100         memset(lg,0,sizeof(lg));
101         memset(rg,0,sizeof(rg));
102         memset(seg,0,sizeof(seg));
103         int o=0;
104         ans=0;
105         mat[num].y = 0;
106         for(i = 0 ; i < num ; i++)
107         {
108             int l = bin(mat[i].lx,0,k-1);
109             int r = bin(mat[i].rx,0,k-1)-1;
110             update(l,r,mat[i].d,0,k-1,1);
111             ans+=seg[1]*(mat[i+1].y-mat[i].y);
112             ans+=abs(sum[1]-o);
113             o = sum[1];
114         }
115         printf("%lld
",ans);
116     }
117     return 0;
118 }
View Code
原文地址:https://www.cnblogs.com/shangyu/p/3320003.html