Picture POJ - 1177

原题链接
考察:线段树
扫描线求周长
思路:
  以x轴为例,先看图.
image
  由此就比较好求了.这里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;
}
posted @ 2021-05-21 01:30  acmloser  阅读(49)  评论(0编辑  收藏  举报