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

概述

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

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("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 1177 Picture [离散化+扫描线+线段树]所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部