HDU 1828 Picture
扫描线,矩形周长并
题意
求矩形周长并
思路
没有想象的难。根面积一样的离散化,线段树保存:
struct Stree
{
int cov;//被完全覆盖的次数
int len;//被覆盖的长度
int num;//区间内线段的数量
int lp, rp;//被覆盖的左端点和右端点
}stree[MAXN<<3];
保存区间内线段的数量,更新时通过左端点和右端点信息判断区间有几段线段。统计周长时:
int la=0, ans=0;
for(int i=1;i<=m;i++)
{
int l=lower_bound(hax+1, hax+k+2, line[i].l)-hax;
int r=lower_bound(hax+1, hax+k+2, line[i].r)-hax-1;
update(l, r, line[i].fl, 1, k, 1);
int tmp=abs(stree[1].len-la);
la=stree[1].len;
ans+=tmp;
if(i!=m) ans+=stree[1].num*2*(line[i+1].h-line[i].h);
}
每次加的长度就是当前长度减上一次长度,同时加上区间内线段数量*2*高度差,就是竖着的那部分线段。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int MAXN=5005;
struct Line
{
int l, r;
int h;
int fl;
Line() {}
Line(int _l, int _r, int _h, int _fl) { l=_l, r=_r, h=_h, fl=_fl; }
bool operator <(const Line &l)const
{
return h<l.h;
}
}line[MAXN<<1];
int hax[MAXN<<1];
struct Stree
{
int cov;//被完全覆盖的次数
int len;//被覆盖的长度
int num;//区间内线段的数量
int lp, rp;//被覆盖的左端点和右端点
}stree[MAXN<<3];
void pushup(int l, int r, int rt)
{
if(stree[rt].cov)
{
stree[rt].len=hax[r+1]-hax[l];
stree[rt].num=1;
stree[rt].lp=l, stree[rt].rp=r;
}
else if(l==r)
{
stree[rt].cov=stree[rt].len=0;
stree[rt].num=0;
stree[rt].lp=stree[rt].rp=0;
}
else
{
stree[rt].len=stree[rt<<1].len+stree[rt<<1|1].len;
stree[rt].lp=stree[rt<<1].lp, stree[rt].rp=stree[rt<<1|1].rp;
stree[rt].num=stree[rt<<1].num+stree[rt<<1|1].num;
if(stree[rt<<1].rp+1==stree[rt<<1|1].lp)
stree[rt].num--;
}
}
void build(int l, int r, int rt)
{
M(stree, 0);
}
void update(int L, int R, int c, int l, int r, int rt)
{
if(L<=l&&r<=R)
{
stree[rt].cov+=c;
pushup(l, r, rt);
return;
}
int mid=(l+r)>>1;
if(R<=mid) update(L, R, c, lson);
else if(mid<L) update(L, R, c, rson);
else
{
update(L, R, c, lson);
update(L, R, c, rson);
}
pushup(l, r, rt);
}
int main()
{
int n;
while(scanf("%d", &n)==1)
{
int m=2*n;
for(int i=1;i<=2*n;i+=2)
{
int a, b, c, d;scanf("%d%d%d%d", &a, &b, &c, &d);
line[i]=Line(a, c, b, 1);
line[i+1]=Line(a, c, d, -1);
hax[i]=a, hax[i+1]=c;
}
sort(line+1, line+m+1);
sort(hax+1, hax+m+1);
int k=unique(hax+1, hax+m+1)-hax-2;
build(1, k, 1);
int la=0, ans=0;
for(int i=1;i<=m;i++)
{
int l=lower_bound(hax+1, hax+k+2, line[i].l)-hax;
int r=lower_bound(hax+1, hax+k+2, line[i].r)-hax-1;
update(l, r, line[i].fl, 1, k, 1);
int tmp=abs(stree[1].len-la);
la=stree[1].len;
ans+=tmp;
if(i!=m) ans+=stree[1].num*2*(line[i+1].h-line[i].h);
}
printf("%d\n", ans);
}
return 0;
}