首页 > 代码库 > hdu1828 (Picture) &poj 1177( Picture)&sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)
hdu1828 (Picture) &poj 1177( Picture)&sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)
题目地址:hdu1828 (Picture) & poj 1177( Picture) & sdibt 2390(5.5.1 Picture 矩形周长)
题目大意:
给你N个矩形,求出N个矩形构成的周长。
解题思路:
线段数+扫描线。
推荐博客: POJ1177 Picture(线段树求轮廓周长)
POJ 1177 Picture (线段树+离散化+扫描线) 详解
注意事项:
该题在求面积的基础上有了升级,多写了一个被调需要求出投影与Y轴有几段,不然样例会少算20,就是给出图形中间的小矩形的上下边没有计算在内。
考虑重边,虽然hdu和poj不考虑也能过,但是sdibt过不了。
重边测试数据:
/*2-10 -10 0 100 -10 10 10
输出:80
不考虑的话会输出:120*/
代码:
1 #include <algorithm> 2 #include <iostream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <string> 8 #include <bitset> 9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #include <cmath> 13 #include <list> 14 #include <map> 15 #include <set> 16 using namespace std; 17 /***************************************/ 18 #define ll long long 19 #define int64 __int64 20 /***************************************/ 21 const int INF = 0x7f7f7f7f; 22 const double eps = 1e-8; 23 const double PIE=acos(-1.0); 24 const int d1x[]= {0,-1,0,1}; 25 const int d1y[]= {-1,0,1,0}; 26 const int d2x[]= {0,-1,0,1}; 27 const int d2y[]= {1,0,-1,0}; 28 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 29 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 30 /***************************************/ 31 void openfile() 32 { 33 freopen("data.in","rb",stdin); 34 freopen("data.out","wb",stdout); 35 } 36 /**********************华丽丽的分割线,以上为模板部分*****************/ 37 const int M=10000; 38 39 struct tree 40 { 41 int left,right;//左右区间 42 double turel,turer,cnt;//记录左右区间的真实值和 投影Y轴坐标的覆盖的程度cnt 43 int lbd,rbd; //辅助求投影Y轴有几段 44 int setline; //记录投影Y轴有几段,假如[1,2][4,5]覆盖在Y轴 45 //说明有两段覆盖在Y轴所以该周长应该是nowline+2(Setline)*2*(line[i].x-line[i-1].x) 46 int c; //记录该区间被覆盖几次。 47 48 } node[M*4]; 49 struct Line 50 { 51 double x,y1,y2; //记录每一条扫描线 52 int f;//标记入边1,出边为-1 53 } line[M];//储存所有的线段 54 int cnt; 55 double y[M];//将y的坐标记录然后离散化 56 bool cmp(Line a,Line b)//排序 57 { 58 if (a.x==b.x) //这句需要有做完该题你会发现有重边的样例过不去, 59 //排序的时候若X某条出边和某条坐标相等将入边排在前面就能解决重边的问题。 60 return a.f>b.f; 61 return a.x<b.x; 62 } 63 void build__tree(int id,int l,int r)//初始化树 64 { 65 int mid=(l+r)/2; 66 node[id].turel=y[l]; 67 node[id].turer=y[r]; 68 node[id].left=l; 69 node[id].right=r; 70 node[id].cnt=0; 71 node[id].c=0; 72 node[id].lbd=0; 73 node[id].rbd=0; 74 node[id].setline=0; 75 if (l+1==r) 76 return ; 77 build__tree(id*2,l,mid); 78 build__tree(id*2+1,mid,r); 79 } 80 //更新line 81 void upline(int i) 82 { 83 if (node[i].c>0) 84 { 85 node[i].lbd=1; 86 node[i].rbd=1; 87 node[i].setline=1; 88 } 89 else if (node[i].right-node[i].left == 1) 90 { 91 node[i].lbd = 0; 92 node[i].rbd = 0; 93 node[i].setline = 0; 94 } 95 else 96 { 97 node[i].lbd = node[2*i].lbd; 98 node[i].rbd = node[2*i+1].rbd; 99 node[i].setline = node[2*i].setline+node[2*i+1].setline-node[2*i].rbd*node[2*i+1].lbd;100 }101 }102 //更新投影Y轴的线段103 void upcnt(int id)104 {105 if (node[id].c>0)106 {107 node[id].cnt=node[id].turer-node[id].turel;108 return ;109 }110 if (node[id].left+1==node[id].right)111 node[id].cnt=0;112 else113 node[id].cnt=node[id*2].cnt+node[id*2+1].cnt;114 }115 void updata(int id,Line v)116 {117 if (node[id].turel==v.y1&&node[id].turer==v.y2)118 {119 node[id].c+=v.f;120 upcnt(id);121 upline(id);122 return ;123 }124 if (v.y2<=node[id*2].turer)125 updata(id*2,v);126 else if (v.y1>=node[id*2+1].turel)127 updata(id*2+1,v);128 else129 {130 Line tmp;131 tmp=v;132 tmp.y2=node[id*2].turer;133 updata(id*2,tmp);134 tmp=v;135 tmp.y1=node[id*2+1].turel;136 updata(id*2+1,tmp);137 }138 upcnt(id);139 upline(id);140 }141 int main()142 {143 int n;144 scanf("%d",&n);145 int i,j;146 int d=1;147 for(i=1; i<=n; i++)148 {149 double x1,x2,y1,y2;150 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);151 line[d].x=x1;152 line[d].y1=y1;153 line[d].y2=y2;154 line[d].f=1;155 y[d]=y1;156 d++;157 line[d].x=x2;158 line[d].y1=y1;159 line[d].y2=y2;160 line[d].f=-1;161 y[d]=y2;162 d++;163 }164 sort(y+1,y+d);165 sort(line+1,line+d,cmp);166 int ncount=unique(y+1,y+d)-(y+1); //去重。167 build__tree(1,1,ncount);168 updata(1,line[1]);169 double sum=0;170 double ce=0;171 double nowline=0;172 int Setline=0;173 for(i=2; i<d; i++)174 {175 Setline=node[1].setline;176 nowline=node[1].cnt-ce;177 if (nowline<0)178 nowline=-nowline;179 if (node[1].cnt==0)180 {181 sum+=(line[i-1].y2-line[i-1].y1);182 ce=0;183 nowline=0;184 }185 else186 sum+=nowline+Setline*2*(line[i].x-line[i-1].x);187 ce=node[1].cnt;188 updata(1,line[i]);189 }190 sum+=(line[i-1].y2-line[i-1].y1);191 printf("%.0f\n",sum);192 return 0;193 }194 /*195 4196 5 5 20 10197 10 0 15 15198 5 5 30 10199 27 8 35 15200 201 2202 -10 -10 0 10203 0 -10 10 10204 */
hdu1828 (Picture) &poj 1177( Picture)&sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。