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\n",ans); 116 } 117 return 0; 118 }