Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4475    Accepted Submission(s): 2207
 
	 
	
题目链接:HDU 1828
扫描线第三道题目,都是整数点且范围较小不需要离散化,主要学习了如何求轮廓线的周长(内周长+外周长),有两种方法这里用的是比较好写但是速度慢的一种——横着竖着各做一次扫描线,统计横竖的周长再求和输出,过程和求面积并类似,但是每一次累加的是覆盖长度的改变量即$abs(这一次更新之后的长度-上一次的长度)$,另外要注意一点就是当高度相同时要优先更新底边。
比如这样一组数据:
2
0 0 1 1
0 1 1 2
若不这样做会得到错误答案8,但其实边长只有4+2=6,原因就是错误地把中间的边也当作影响更新长度的情况了,实际是重叠之后两条边会一起抵消掉,刚开始写完debug半天最后发现是建树时没考虑范围要可能是负数……
代码:
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=2e4+7;
struct seg
{
    int l,mid,r;
    int len,cnt;
};
struct Line
{
    int l,r,h,flag;
    inline bool operator<(const Line &t)const
    {
        if(h==t.h)//若高度相等,则底边优先
            return flag>t.flag;
        return h<t.h;
    }
};
seg T[N<<2];
Line xline[N],yline[N];
inline void pushup(int k)
{
    if(T[k].cnt)
        T[k].len=T[k].r-T[k].l+1;
    else
    {
        if(T[k].l==T[k].r)
            T[k].len=0;
        else
            T[k].len=T[LC(k)].len+T[RC(k)].len;
    }
}
void build(int k,int l,int r)
{
    T[k].l=l;
    T[k].r=r;
    T[k].mid=MID(l,r);
    T[k].cnt=0;
    T[k].len=0;
    if(l==r)
        return ;
    build(LC(k),l,T[k].mid);
    build(RC(k),T[k].mid+1,r);
}
void update(int k,int l,int r,int flag)
{
    if(l<=T[k].l&&T[k].r<=r)
    {
        T[k].cnt+=flag;
        pushup(k);
    }
    else
    {
        if(r<=T[k].mid)
            update(LC(k),l,r,flag);
        else if(l>T[k].mid)
            update(RC(k),l,r,flag);
        else
            update(LC(k),l,T[k].mid,flag),update(RC(k),T[k].mid+1,r,flag);
        pushup(k);
    }
}
int main(void)
{
    int n,i;
    int xa,xb,ya,yb;
    int ans,last;
    while (~scanf("%d",&n))
    {
        int cnt=0;
        int xR=-INF;
        int yR=-INF;
        int xL=INF;
        int yL=INF;
        for (i=0; i<n; ++i)
        {
            scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
            xline[cnt]=(Line){xa,xb,ya,1};
            yline[cnt++]=(Line){ya,yb,xa,1};//
            xline[cnt]=(Line){xa,xb,yb,-1};
            yline[cnt++]=(Line){ya,yb,xb,-1};//
            if(xa>xR) xR=xa;
            if(xa<xL) xL=xa;
            if(xb>xR) xR=xb;
            if(xb<xL) xL=xb;
            if(ya>yR) yR=ya;
            if(ya<yL) yL=ya;
            if(yb>yR) yR=yb;
            if(yb<yL) yL=yb;
        }
        ans=0;
        sort(xline,xline+cnt);
        sort(yline,yline+cnt);
        last=0;
        build(1,xL,xR);
        for (i=0; i<cnt; ++i)
        {
            update(1,xline[i].l,xline[i].r-1,xline[i].flag);
            ans=ans+abs(T[1].len-last);
            last=T[1].len;
        }
        last=0;
        build(1,yL,yR);
        for (i=0; i<cnt; ++i)
        {
            update(1,yline[i].l,yline[i].r-1,yline[i].flag);
            ans=ans+abs(T[1].len-last);
            last=T[1].len;
        }
        printf("%d\n",ans);
    }
    return 0;
}
原文:http://www.cnblogs.com/Blackops/p/6028699.html