Picture POJ - 1177
原题链接
考察:线段树
扫描线求周长
思路:
以x轴为例,先看图.
由此就比较好求了.这里cnt有值就可以贡献长度,所以可以不用push_down.
Code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 5010;
struct Segment{
int a,b1,b2,k;
bool operator<(const Segment& s){
if(this->a!=s.a) return this->a<s.a;
return this->k>s.k;
}
}seg[2][N<<1];
struct Node{
int l,r,cnt,len;
}tr[N<<3];
int n,idx[2],op;
vector<int> v[2];
void add(int a,int b1,int b2,int s)
{
seg[s][++idx[s]].a = a;
seg[s][idx[s]].b1 = b1;
seg[s][idx[s]].b2 = b2;
seg[s][idx[s]].k = idx[s]%2==1?1:-1;
}
int get(int x,int s)
{
return lower_bound(v[s].begin(),v[s].end(),x)-v[s].begin()+1;
}
void build(int u,int l,int r)
{
tr[u].l = l,tr[u].r = r,tr[u].cnt = 0,tr[u].len = 0;
if(l==r) return;
int mid = l+r>>1;
build(u<<1,l,mid); build(u<<1|1,mid+1,r);
}
int rget(int x,int s)
{
return v[s][x-1];
}
void push_up(int u)
{
if(tr[u].cnt) tr[u].len = rget(tr[u].r+1,op)-rget(tr[u].l,op);
else if(tr[u].l!=tr[u].r) tr[u].len = tr[u<<1].len+tr[u<<1|1].len;
else tr[u].len = 0;
}
void modify(int u,int l,int r,int w)
{
if(tr[u].l>=l&&tr[u].r<=r)
{
tr[u].cnt+=w;
push_up(u);
return;
}
int mid = tr[u].l+tr[u].r>>1;
if(l<=mid) modify(u<<1,l,r,w);
if(mid<r) modify(u<<1|1,l,r,w);
push_up(u);
}
int work(int s)
{
sort(seg[s]+1,seg[s]+idx[s]+1);
build(1,1,v[s].size());
int res = 0,temp = 0,now = 0;
for(int i=1;i<=idx[s];i++)
{
int l = get(seg[s][i].b1,s),r = get(seg[s][i].b2,s);
temp = tr[1].len;
modify(1,l,r-1,seg[s][i].k);
now = tr[1].len;
res+=abs(now-temp);
}
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
add(x1,y1,y2,0); add(x2,y1,y2,0);
add(y1,x1,x2,1); add(y2,x1,x2,1);
v[0].push_back(y1),v[0].push_back(y2);
v[1].push_back(x1),v[1].push_back(x2);
}
sort(v[0].begin(),v[0].end());
sort(v[1].begin(),v[1].end());
v[0].erase(unique(v[0].begin(),v[0].end()),v[0].end());
v[1].erase(unique(v[1].begin(),v[1].end()),v[1].end());
int ans = work(0);
op++;
ans+=work(1);
printf("%d\n",ans);
return 0;
}