POJ 1177 Picture [离散化+扫描线+线段树]
2015-05-01 11:51
393 查看
http://poj.org/problem?id=1177
给若干矩形,求被覆盖的区域的周长。
将 y 坐标离散化后,按 x 坐标进行扫描。用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 cnt 。 前一个用来计算竖直方向的周长部分,后一个用来计算水平方向的。
用 left[node] 和 right[node] 来记录每个结点左端和右端是否被覆盖,用来维护 cnt
重叠的边也不能计算,这反应在对扫描线的排序上,两线重叠时入边应在出边之前。
给若干矩形,求被覆盖的区域的周长。
将 y 坐标离散化后,按 x 坐标进行扫描。用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 cnt 。 前一个用来计算竖直方向的周长部分,后一个用来计算水平方向的。
用 left[node] 和 right[node] 来记录每个结点左端和右端是否被覆盖,用来维护 cnt
重叠的边也不能计算,这反应在对扫描线的排序上,两线重叠时入边应在出边之前。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; #define CHD int lc = node<<1,rc = node<<1|1; #define MID int mid = (L+R)>>1; #define debug(x) cout<<"debug "<<x<<endl; #define rep(i,f,t) for(int i = (f),_end =(t); i <= _end; ++i) struct Node{ int x; int y1,y2; int flag; //入边为1,出边为-1 Node(int x,int y1,int y2,int f) :x(x),y1(y1),y2(y2),flag(f){ } bool operator< (const Node &n2)const{ if(x == n2.x)return flag > n2.flag;//入边在出边前 return x < n2.x; } }; vector<Node> line; vector<int> vs; const int maxn = 10005; struct sgt{ int len[maxn<<2]; int cnt[maxn<<2]; int cov[maxn<<2]; int left[maxn<<2]; int right[maxn<<2]; void maintain(int node,int L,int R){ if(cov[node] > 0){ len[node] = vs[R]-vs[L-1]; cnt[node] = 1; left[node] = right[node] = 1; } else { if(L == R){ len[node] = 0; cnt[node] = 0; left[node] = right[node] = 0; }else{ CHD; len[node] = len[lc]+len[rc]; cnt[node] = cnt[lc]+cnt[rc]-(left[rc]&right[lc]); left[node] = left[lc]; right[node] = right[rc]; } } } void update(int from,int to,int val,int node,int L,int R){ if(from <= L && R <= to){ cov[node] += val; } else { MID;CHD; if(from <= mid) update(from,to,val,lc,L,mid); else maintain(lc,L,mid); if(to > mid) update(from,to,val,rc,mid+1,R); else maintain(rc,mid+1,R); } maintain(node,L,R); } int solve(){ int ans = 0,ans2 = 0;//竖直和水平方向的周长 int n = vs.size()-1; int last = 0; rep(i,0,line.size()-1){ int x = line[i].x; int f = line[i].y1+1; int t = line[i].y2; if(i > 0){ int tmp = cnt[1] * (x-line[i-1].x); ans2 += tmp*2; } update(f,t,line[i].flag,1,1,n); ans += abs(last-len[1]);//竖直方向长度变化 last = len[1]; } return ans+ans2; } }tree; void pre(){ sort(vs.begin(),vs.end()); vs.erase(unique(vs.begin(),vs.end()),vs.end()); rep(i,0,line.size()-1){ line[i].y1 = lower_bound(vs.begin(),vs.end(),line[i].y1) - vs.begin(); line[i].y2 = lower_bound(vs.begin(),vs.end(),line[i].y2) - vs.begin(); } sort(line.begin(),line.end()); } int main(){ int n; scanf("%d",&n); if(n == 0){ printf("0\n"); return 0; } line.reserve(n<<1); vs.reserve(n<<1); rep(i,1,n){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); vs.push_back(y1); vs.push_back(y2); line.push_back(Node(x1,y1,y2,1)); line.push_back(Node(x2,y1,y2,-1)); } pre(); int ans = tree.solve(); printf("%d\n",ans); return 0; }
相关文章推荐
- poj 1177 picture(线段树+扫描线+离散化)★
- poj_1151 Atlantis && poj_1177 Picture(线段树+扫描线+离散化)
- HDU 1828 && POJ 1177 Picture(线段树+扫描线+离散化)
- POJ-1177-Picture(线段树+扫描线+离散化)[矩形周长并]
- POJ 1177 Picture [离散化+扫描线+线段树]
- poj 1177 || HDU 1828 Picture (线段树扫描线求 图形并的周长)
- POJ-1177-Picture(线段树+Y方向离散化+读取perimeterのX方向的扫描)
- POJ 1177 Picture (线段树扫描线)
- poj 1177 & hdu 1828 Picture(线段树+离散化)
- poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)
- POJ 1177 Picture(线段树+离散化 求周长)
- poj - 1177 - Picture(离线化+扫描线+线段树)
- poj&nbsp;1177&nbsp;Picture&nbsp;线段树加扫描线
- poj 1151 Atlantis (线段树+扫描线+离散化)
- POJ 1177 Picture(扫描线 + 线段树 矩形覆盖区域周长的并)
- poj 1177 Picture 【线段树 扫描线 求轮廓周长】
- 【POJ】1171 求矩形并的周长(线段树+扫描线+离散化)
- POJ 1177:Picture(线段树-扫描线)
- POJ - 1177/HDU - 1828 Picture(线段树-矩形并周长)
- poj 1177 经典线段树+扫描线就周长并