我是靠谱客的博主 甜甜大神,这篇文章主要介绍POJ 1177 Picture [离散化+扫描线+线段树],现在分享给大家,希望可以做个参考。

http://poj.org/problem?id=1177
给若干矩形,求被覆盖的区域的周长。

y 坐标离散化后,按 x 坐标进行扫描。用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 cnt 。 前一个用来计算竖直方向的周长部分,后一个用来计算水平方向的。
left[node]right[node] 来记录每个结点左端和右端是否被覆盖,用来维护 cnt

重叠的边也不能计算,这反应在对扫描线的排序上,两线重叠时入边应在出边之前。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#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("0n"); 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("%dn",ans); return 0; }

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/DSChan/p/4861973.html

最后

以上就是甜甜大神最近收集整理的关于POJ 1177 Picture [离散化+扫描线+线段树]的全部内容,更多相关POJ内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部