zoukankan      html  css  js  c++  java
  • HDU

    题目链接

    题意 

    多个矩形重叠在一起,求出轮廓线的长度。

    分析 

    把矩形分成横线和竖线来处理。现在分析横线的,竖线同理。矩形的坐标都是整数,且范围不大,故此题不需要离散化。从下往上扫描横线,每遇到一条横线,就计算长度,矩形的下边标为1,上边标为-1。具体计算方法是此次区间的总覆盖长度与上次区间长度相比,若没有变化,则说明新加入的横线是重叠的。故每次计算的答案便是两者之差的绝对值。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include <queue>
    #include <vector>
    #include<bitset>
    #include<map>
    #include<deque>
    using namespace std;
    typedef long long LL;
    const int maxn = 10010;
    const int mod = 77200211+233;
    typedef pair<int,int> pii;
    #define X first
    #define Y second
    #define pb push_back
    //#define mp make_pair
    #define ms(a,b) memset(a,b,sizeof(a))
    const int inf = 0x3f3f3f3f;
    #define lson l,m,2*rt
    #define rson m+1,r,2*rt+1
    
    struct edge{
        int l,r,h,f;
    }ex[2*maxn],ey[maxn*2];
    
    struct node{
        int l,r,cover,len;
        int mid(){
            return (l+r)>>1;
        }
    }tree[maxn*8];
    
    int cmp(edge a,edge b){
        return a.h<b.h;
    }
    
    void build(int l,int r,int rt){
        tree[rt].l=l,tree[rt].r=r;
        tree[rt].len=tree[rt].cover=0;
        if(l+1==r) return;
        int mid = tree[rt].mid();
        build(l,mid,rt<<1);
        build(mid,r,rt<<1|1);
    }
    
    void push_up(int rt){
        if(tree[rt].cover){
            tree[rt].len=tree[rt].r-tree[rt].l;
        }else if(tree[rt].l+1==tree[rt].r){
            tree[rt].len=0;
        }else{
            tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;
        }
        return;
    }
    
    void update(edge e,int rt){
        if(tree[rt].l==e.l&&tree[rt].r==e.r){
            tree[rt].cover+=e.f;
            push_up(rt);
            return;
        }
        int m=tree[rt].mid();
        if(e.r<=m) update(e,rt<<1);
        else if(e.l>=m) update(e,rt<<1|1);
        else{
            edge temp = e;
            temp.r=m;
            update(temp,rt<<1);
            temp = e;
            temp.l=m;
            update(temp,rt<<1|1);
        }
        push_up(rt);
    }
    int ans;
    void work(int l,int r,edge seg[],int n){
        build(l,r,1);
        int prelen=0;
        for(int i=0;i<n;i++){
            update(seg[i],1);
            ans += abs(tree[1].len-prelen);
            prelen=tree[1].len;
        }
    }
    
    int main(){
        int n,x1,x2,y1,y2;
        while(~scanf("%d",&n)){
            if(n==0){
                puts("0");
                continue;
            }
        
            int maxx,maxy,minx,miny;
            maxx=maxy=-inf,minx=miny=inf;
            int cnt=0;
            for(int i=0;i<n;i++){
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                //横向
                ex[cnt].l=ex[cnt+1].l=x1,
                ex[cnt].r=ex[cnt+1].r=x2,
                ex[cnt].h=y1,ex[cnt+1].h=y2,
                ex[cnt].f=1,ex[cnt+1].f=-1;
    
                ey[cnt].l=ey[cnt+1].l=y1,
                ey[cnt].r=ey[cnt+1].r=y2,
                ey[cnt].h=x1,ey[cnt+1].h=x2,
                ey[cnt].f=1,ey[cnt+1].f=-1;
                cnt+=2;
    
                maxx=max(maxx,max(x1,x2));
                minx=min(minx,min(x1,x2));
                miny=min(miny,min(y1,y2));
                maxy=max(maxy,max(y1,y2));
            }
    
            sort(ex,ex+cnt,cmp);
            sort(ey,ey+cnt,cmp);
            ans=0;
            work(minx,maxx,ex,cnt);
            work(miny,maxy,ey,cnt);
            printf("%d
    ",ans);
        }
        return 0;
    }

    还有一种更好的做好,参见http://www.cnblogs.com/scau20110726/archive/2013/04/13/3018687.html

    同时计算横线和竖线

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 5010
    #define MAX 10100
    #define lch(i) ((i)<<1)
    #define rch(i) ((i)<<1|1)
    
    struct segment{
        int l,r,h,v;
    }s[2*N];
    struct node{
        int l,r,lp,rp,cnt,len,num;
        int mid()
        { return (l+r)>>1; }
    }t[2*MAX*4];
    
    int cmp(struct segment p ,struct segment q)
    {
        return p.h<q.h;
    }
    
    void build(int l ,int r, int rt)
    {
        t[rt].l=l; t[rt].r=r;
        t[rt].cnt=t[rt].len=0;
        t[rt].lp=t[rt].rp=t[rt].num=0;
        if(l==r) return ;
        int mid=t[rt].mid();
        build(l,mid,lch(rt));
        build(mid+1,r,rch(rt));
    }
    
    void cal(int rt)
    {
        if(t[rt].cnt)
        {
            t[rt].len=t[rt].r-t[rt].l+1;
            t[rt].lp=t[rt].rp=1;
            t[rt].num=1;
        }
        else if(t[rt].l == t[rt].r) //叶子
        {
            t[rt].len=0;
            t[rt].lp=t[rt].rp=0;
            t[rt].num=0;
        }
        else
        {
            t[rt].len=t[lch(rt)].len+t[rch(rt)].len;
            t[rt].lp=t[lch(rt)].lp; 
            t[rt].rp=t[rch(rt)].rp;
            t[rt].num=t[lch(rt)].num + t[rch(rt)].num - (t[lch(rt)].rp&t[rch(rt)].lp);
        }
    }
    
    void updata(int l ,int r ,int v ,int rt)
    {
        if(t[rt].l==l && t[rt].r==r) //目标区间
        {
            t[rt].cnt += v;
            cal(rt);
            return ;
        }
        int mid=t[rt].mid();
        if(r<=mid)     updata(l,r,v,lch(rt));
        else if(l>mid) updata(l,r,v,rch(rt));
        else
        {
            updata(l,mid,v,lch(rt));
            updata(mid+1,r,v,rch(rt));
        }
        cal(rt);
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0) 
            { puts("0"); continue; }
            int i,maxx,minx,m;
            for(i=0,m=0,maxx=-MAX,minx=MAX; i<n; i++,m+=2)
            {
                int x1,y1,x2,y2;
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                maxx=max(maxx,x2);
                minx=min(minx,x1);
                s[m].l=x1;   s[m].r=x2;   s[m].h=y1;   s[m].v=1;
                s[m+1].l=x1; s[m+1].r=x2; s[m+1].h=y2; s[m+1].v=-1;
            }
            sort(s,s+m,cmp);
            build(minx,maxx-1,1);
            int res=0 , prelen=0;
            s[m]=s[m+1]; //每次处理循环的最后一次
            for(int i=0; i<m; i++)
            {
                updata(s[i].l,s[i].r-1,s[i].v,1);
                res += abs(t[1].len-prelen); //计算横线部分
                res += (s[i+1].h-s[i].h)*(2*t[1].num); //计算竖线部分
                prelen=t[1].len;
            }
            printf("%d
    ",res);
        }
        return 0;
    }
  • 相关阅读:
    CSS笔记
    EasyUI笔记
    EasyUI treegrid 获取编辑状态中某字段的值 [getEditor方法获取不到editor]
    2019.10.12解题报告
    %lld 和 %I64d
    关于kmp算法
    洛谷p2370yyy2015c01的U盘题解
    About me & 友链
    关于Tarjan
    洛谷p3398仓鼠找suger题解
  • 原文地址:https://www.cnblogs.com/fht-litost/p/8653102.html
Copyright © 2011-2022 走看看