HDU1828 Picture

-----------------------

扫描线求周长

链接(HDU):Miku

链接(Vjudge):Miku

-----------------------

HDU是多组数据!!!而且不写明白了!!!

我本以为既然多组数据,何不写上一共几组,既然不写,那必然是不存在了

但是它就是多组数据

----------------------

这道题显然的做法是扫描两次,横着一次竖着一次,不过会很繁琐

事实上,一次就够了

-----------------------

完全可以从上向下扫描一次,对于竖线,显然就是两条线段之间的高度*区间个数*2(更新前)

而对于横线,就是两次的区间长度之差的绝对值(因为无论是+还是-,裸露出来的就是变化的长度)
-------------------------

这样就变成了两个小问题了

横线的求法,没有特别之处,但是竖线,因为是求区间线段数,就要特别处理一下了

我用了额外两个数组,ld,rd,代表一个区间的左右端点是否被覆盖,显然左端点就是左儿子左端点,右端点同理

但是如果左右儿子连起来了,还要特判

所以pushup更长了

void pushup(int x,int l,int r){
    if(lazy[x]>=1){
        sum[x]=r-l+1;
        summ[x]=2;
        ld[x]=rd[x]=1;
        }
    else if(l!=r){
        sum[x]=sum[x<<1]+sum[x<<1|1];
        ld[x]=ld[x<<1];
        rd[x]=rd[x<<1|1];
        summ[x]=summ[x<<1]+summ[x<<1|1];
        if(ld[x<<1|1]&&rd[x<<1]) summ[x]-=2;
        }
    else{
        sum[x]=0;
        summ[x]=0;
        ld[x]=0;
        rd[x]=0;
        }
}

---------------------------

这样来看,整个代码也就呼之欲出了

-----------------------------

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int xx,yy,xxx,yyy;
long long ans;
const int maxn=100000;
int last;
struct li{
    int l;
    int r;
    long long  h;
    int f;
}line[200005];
int n;
int p;
int sum[4000005];
bool ld[4000005],rd[4000005];
int lazy[4000005];
int summ[4000005];
int lm;
int rm;
bool cmp(li x,li y){
    return x.h<y.h;
}
void pushup(int x,int l,int r){
    if(lazy[x]>=1){
        sum[x]=r-l+1;
        summ[x]=2;
        ld[x]=rd[x]=1;
        }
    else if(l!=r){
        sum[x]=sum[x<<1]+sum[x<<1|1];
        ld[x]=ld[x<<1];
        rd[x]=rd[x<<1|1];
        summ[x]=summ[x<<1]+summ[x<<1|1];
        if(ld[x<<1|1]&&rd[x<<1]) summ[x]-=2;
        }
    else{
        sum[x]=0;
        summ[x]=0;
        ld[x]=0;
        rd[x]=0;
        }
}
void update(int x,int l,int r,int L,int R,int d){
    if(L<=l&&r<=R){
        lazy[x]+=d;
        pushup(x,l,r);
        return ;
    }
    int mid=(l+r)>>1;
    if(L<=mid) update(x<<1,l,mid,L,R,d);
    if(R>mid) update(x<<1|1,mid+1,r,L,R,d);
    pushup(x,l,r);
}
int main(){
    while(~scanf("%d",&n)){
        cin>>n;
        p=0;
        ans=0;
        last=0;
        lm=-10000;
        rm=10000;
    for(int i=1;i<=n;++i){
        scanf("%d%d%d%d",&xx,&yy,&xxx,&yyy);
        lm=min(lm,xx);
        rm=max(rm,xxx);
        p++;
        line[p].l=xx;
        line[p].r=xxx;
        line[p].h=yy;
        line[p].f=1;
        p++;
        line[p].l=xx;
        line[p].r=xxx;
        line[p].h=yyy;
        line[p].f=-1;
    }
    sort(line+1,line+p+1,cmp);
    for(int i=1;i<=p;++i){
        update(1,lm,rm-1,line[i].l,line[i].r-1,line[i].f);
        ans+=summ[1]*(line[i+1].h-line[i].h);
        ans+=abs(sum[1]-last);
        last=sum[1];
        }
    cout<<ans;
    }
    return 0;
}

不知道为啥,这份代码从左往右扫会有BUG

posted @ 2020-03-14 08:11  Simex  阅读(355)  评论(5编辑  收藏  举报