POJ 1177 线段树 扫描线 模板题

来源:互联网 发布:热动力学分析软件 编辑:程序博客网 时间:2024/05/18 15:08

和POJ 1151 差不多  

求矩阵周长

主要把callen函数改下就行了



#include "stdio.h"#include "string.h"#include "math.h"#include "stdlib.h"#include "iostream"#include "algorithm"using namespace std;struct comp{int x,y1,y2,flag;} node[10010];struct comp1{int l,r,mid,mr,ml;int s; // 当前区间是否被覆盖int num;  // 所覆盖的区间包含几个矩形int l_cover,len,r_cover; // 分别记录左右端点是否覆盖} data[100010];bool cmp(comp a,comp b){return a.x<b.x;}int y[10010];void build(int l,int r,int k){data[k].l=l;data[k].r=r;data[k].mid=(l+r)/2;data[k].s=data[k].num=data[k].l_cover=data[k].r_cover=0;data[k].mr=y[r];data[k].ml=y[l];if (l+1==r) return ;build(l,data[k].mid,k*2);build(data[k].mid,r,k*2+1);}void callen(int k){if (data[k].s>0){data[k].len=data[k].mr-data[k].ml;data[k].r_cover=data[k].l_cover=data[k].num=1;}else if (data[k].l+1==data[k].r){data[k].len=0;data[k].r_cover=data[k].l_cover=data[k].num=0;}else {data[k].len=data[k*2].len+data[k*2+1].len;data[k].l_cover=data[k*2].l_cover;data[k].r_cover=data[k*2+1].r_cover;data[k].num=data[k*2].num+data[k*2+1].num-data[k*2].r_cover*data[k*2+1].l_cover;}}void updata(int k,comp b){if (b.y2==data[k].mr && b.y1==data[k].ml){data[k].s+=b.flag;callen(k);return ;}if (b.y2<=data[k*2].mr) updata(k*2,b);else if (b.y1>=data[k*2+1].ml) updata(k*2+1,b);else {comp temp;temp=b;temp.y2=data[k*2].mr;updata(k*2,temp);temp=b;temp.y1=data[k*2+1].ml;updata(k*2+1,temp);}callen(k);}int main(){int n,x1,i,y1,x2,y2,t,len,sum,pre;while (scanf("%d",&n)!=EOF){t=0;for (i=0;i<n;i++){scanf("%d%d%d%d",&x1,&y1,&x2,&y2);node[t].x=x1;node[t].y1=y1;node[t].y2=y2;node[t].flag=1;y[t++]=y1;node[t].x=x2;node[t].y1=y1;node[t].y2=y2;node[t].flag=-1;y[t++]=y2;}sort(y,y+t);sort(node,node+t,cmp);len=1;for (i=1;i<t;i++) // 一定要去重边,否则WAif (y[i]!=y[i-1])y[len++]=y[i];len--;build(0,len,1);sum=0;pre=0;for (i=0;i<t;i++){updata(1,node[i]);sum+=abs(data[1].len-pre); if (i==t-1) break;pre=data[1].len;sum+=data[1].num*(node[i+1].x-node[i].x)*2;}printf("%d\n",sum);}return 0;}