hdu 1828(扫描线+线段树)

扫描线求周长,题干又问题,没说要多组输入啊,不多组输入就wr,让我找了好长时间

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=2e4+100;
struct note
{
    int l,r,h;
    int ff;
    note() {}
    note(int l,int r,int h,int ff):l(l),r(r),h(h),ff(ff) {}
    bool operator < (const note &p) const
    {
        return h<p.h;
    }
} aa[maxn];
int col[maxn<<2],sum[maxn<<2],ll[maxn<<2],rr[maxn<<2];
int linenum[maxn<<2];
void pushup(int l,int r,int rt)
{
    if(col[rt])
    {
        sum[rt]=r-l+1;
        linenum[rt]=2;
        ll[rt]=rr[rt]=1;
    }
    else if(l==r)
    {
        sum[rt]=linenum[rt]=ll[rt]=rr[rt]=0;
    }
    else
    {
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
        ll[rt]=ll[rt<<1];
        rr[rt]=rr[rt<<1|1];
        linenum[rt]=linenum[rt<<1]+linenum[rt<<1|1];
        if(rr[rt<<1]&&ll[rt<<1|1])  linenum[rt]-=2;//两条线能接在一起,那么将内侧的边减去
    }
}
void update(int L,int R,int v,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        col[rt]+=v;
        pushup(l,r,rt);
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) update(L,R,v,l,mid,rt<<1);
    if(R>mid) update(L,R,v,mid+1,r,rt<<1|1);
    pushup(l,r,rt);
}
int n;
int main()
{
    while(~scanf("%d",&n))
    {
        int mini=10000,maxi=-10000;
        int a,b,c,d;
        int cnt=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            cnt++;
            aa[cnt]=note(a,c,b,1);
            cnt++;
            aa[cnt]=note(a,c,d,-1);
            mini=min(mini,a);
            maxi=max(maxi,c);
        }
        sort(aa+1,aa+1+cnt);
        int ans=0;
        int zz=0;
        for(int i=1; i<=cnt; i++)
        {
            if(aa[i].l<aa[i].r) update(aa[i].l,aa[i].r-1,aa[i].ff,mini,maxi,1);
            ans+=abs(zz-sum[1]);
            ans+=linenum[1]*(aa[i+1].h-aa[i].h);
            zz=sum[1];
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Wangwanxiang/p/9435247.html