zoukankan      html  css  js  c++  java
  • hdu4052矩形面积并

    建模需要注意下细节,,这是做扫描线的惯例,就是最好把模型建立在笛卡尔坐标系上

    剩下的看链接和注释https://blog.csdn.net/shiqi_614/article/details/7983508

    /*
    扫描线解一个被覆盖了一些面积的区间 
    问能空余地方能放置多少个1*M或M*1的矩形
    设[i,j]为可以作为矩形放置起点的方块,那么只要统计出不能作为起点的方块的面积即可
    本题用的是点的行列号,转换成笛卡尔坐标系上的坐标即可
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    #define ll long long 
    #define maxn 100005
    #define lson l,m,rt<<1
    #define rson m,r,rt<<1|1
    using namespace std;
    struct Seg{
        int x,y1,y2,c;
        Seg(){}
        Seg(int a,int b,int c,int d):x(a),y1(b),y2(c),c(d){}
        bool operator<(const Seg & a){return x<a.x;}
    }segs[maxn];
    map<int,int>mp;
    int y[maxn],data[maxn][4],tot,toty;
    int sum[maxn<<2],flag[maxn<<2];
    
    void pushup(int rt,int l,int r){
        if(flag[rt]>0)
            sum[rt]=y[r]-y[l];
        else {
            if(l+1==r) sum[rt]=0;
            else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
        }
    }
    void update(int L,int R,int c,int l,int r,int rt){
        if(L<=l && R>=r){
            flag[rt]+=c;
            pushup(rt,l,r);
            return;
        }
        int m=l+r>>1;
        if(L<m) update(L,R,c,lson);
        if(R>m) update(L,R,c,rson);
        pushup(rt,l,r);
    }
    ll solve(int n,int w,int h,int m){
        memset(y,0,sizeof y);
        memset(segs,0,sizeof segs);
        memset(sum,0,sizeof sum);
        memset(flag,0,sizeof flag);
        mp.clear();
        tot=toty=0;
    
        y[toty++]=1,y[toty++]=h;
        segs[tot++]=Seg(max(1,w-m),1,h,1);
        segs[tot++]=Seg(w,1,h,-1);
        for(int i=0;i<n;i++){
            int x1=max(1,data[i][0]-m),y1=data[i][1];
            int x2=data[i][2],y2=data[i][3];
            segs[tot++]=Seg(x1,y1,y2,1);
            segs[tot++]=Seg(x2,y1,y2,-1);
            y[toty++]=y1;y[toty++]=y2;
        }
        sort(y,y+toty);
        toty=unique(y,y+toty)-y;
        for(int i=0;i<toty;i++) mp[y[i]]=i;
        sort(segs,segs+tot);
    
        ll res=0;
        for(int i=0;i<tot;i++){
            if(i!=0) res+=(ll)(segs[i].x-segs[i-1].x)*sum[1];
            update(mp[segs[i].y1],mp[segs[i].y2],segs[i].c,0,toty-1,1);
    //    cout << res<<endl;
        }
    //    cout << res << endl <<endl;
        return res;
    }
    int main(){
        int w,h,n,m;
        while(scanf("%d%d%d%d",&w,&h,&n,&m)==4){
            for(int i=0;i<n;i++)
                for(int j=0;j<4;j++){
                    scanf("%d",&data[i][j]);
                    if(j==2||j==3)data[i][j]++;
                }
            ll res1=(ll)(w*h)-solve(n,w+1,h+1,m-1);//把点行列号转换成笛卡尔坐标,即把点扩展成一块单位面积
            for(int i=0;i<n;i++){//对换矩形的xy轴坐标
                swap(data[i][0],data[i][1]);
                swap(data[i][2],data[i][3]);
            }   
            ll res2=(ll)(w*h)-solve(n,h+1,w+1,m-1);
               //cout << res1 << " " << res2 << endl;
            if(m!=1) printf("%lld
    ",res1+res2);
            else printf("%lld
    ",res1);//注意这个细节
        }
        return 0;
    }
  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9966324.html
Copyright © 2011-2022 走看看