• 线段树 扫描线 HDU 1828


    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #include<math.h>
    
    using namespace std;
    
    #define inf 100000000
    #define MAXN 5010
    #define MAXN 20010
    struct edge 
    {
        int l,r,h,f;  //线段的 左边 右边 高度 
    
    }x[MAXN<<1];
    struct node
    {
        int l,r,len,s; // 左边 右边 现在覆盖的长度 
        bool lc,rc;    //左右端点是否覆盖
        int num;       //这个区间上多少个线段
    }z[MAXN<<3];
    bool cmp(edge a,edge b)
    {
        return a.h<b.h;
    }
    void Build(int l,int r,int a)
    {
        z[a].l=l;
        z[a].r=r;
        z[a].s=z[a].len=0;
        z[a].lc=z[a].rc=z[a].num=0;
        if(l==r)
            return ;
        int mid=(l+r)>>1;
        Build(l,mid,a<<1);
        Build(mid+1,r,a<<1|1);
    }
    void push_up(int a) //区间合并
    {
        if(z[a].s)//整个都被覆盖
        {
            z[a].len=z[a].r-z[a].l+1;
            z[a].lc=z[a].rc=1;
            z[a].num=1;
        }
        else if(z[a].l==z[a].r) //单个的点
        {
            z[a].len=0;
            z[a].lc=z[a].rc=0;
            z[a].num=0;
        }
        else  //一段区间
        {
            z[a].len=z[a<<1].len+z[a<<1|1].len;
            z[a].lc=z[a<<1].lc;
            z[a].rc=z[a<<1|1].rc;
            z[a].num=z[a<<1].num+z[a<<1|1].num-(z[a<<1].rc&z[a<<1|1].lc);
        }
    }
    void update(int l,int r,int a1,int b1,int f,int a)
    {
        if(a1<=l&&r<=b1)
        {
            z[a].s+=f;
            push_up(a);
            return ;
        }
        int mid=(l+r)>>1;
        if(a1<=mid)
            update(l,mid,a1,b1,f,a<<1);
        if(b1>mid)
            update(mid+1,r,a1,b1,f,a<<1|1);
        push_up(a);
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            int x1,x2,y1,y2,mx=-inf,mn=inf;
            int cnt=0;
    
            for(int i=0;i<n;i++)
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                mx=max(mx,max(x1,x2));//维护最小和最大
                mn=min(mn,min(x1,x2));
                x[cnt].l=x[cnt+1].l=x1;
                x[cnt].r=x[cnt+1].r=x2;
                x[cnt].h=y1;
                x[cnt+1].h=y2;
                x[cnt].f=1;
                x[cnt+1].f=-1;
                cnt+=2;
            }
            sort(x,x+cnt,cmp);   //按高度排序
            Build(mn,mx-1,1);    //这边要减一
            int last=0,ans=0;
            for(int i=0;i<cnt;i++)
            {
                update(mn,mx-1,x[i].l,x[i].r-1,x[i].f,1);
                ans+=abs(z[1].len-last);  //这次和上次覆盖的差
                ans+=(x[i+1].h-x[i].h)*2*z[1].num;//高度乘以数目
                last=z[1].len;
            }
    
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    30天养成一个好习惯
    ym——安卓巴士总结了近百个Android优秀开源项
    内存泄漏以及常见的解决方法
    Android学习笔记(四十):Preference的使用
    Android中View绘制流程以及invalidate()等相关方法分析
    NumberFormat 类
    开发人员福利!ChromeSnifferPlus 插件正式登陆 Chrome Web Store
    memset函数具体说明
    分分钟教会你使用HTML写Web页面
    UVA 465 (13.08.02)
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6287230.html
Copyright © 2020-2023  润新知