您的位置:首页 > 其它

POJ 1177 Picture [离散化+扫描线+线段树]

2015-05-01 11:51 330 查看
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("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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: