850. 矩形面积 II 线段树+扫描线,acmer的简洁代码

acm经典线段树入门题,leetcode的困难题。。

不过ACMer能快速手敲出这题的应该不多吧,至少我们学校应该没几个。。

const int M = 410;
typedef long long ll;
const int mod = 1e9+7;
#define ls o*2
#define rs (o*2+1)
class Solution {
public:

    struct LINE{
        ll x,y1,y2,op;
        bool operator < (const LINE &r)const{
            return x<r.x;
        }
    }line[M];
    int n;
    vector<int>li;
    //横坐标为x的情况下,纵坐标区间被覆盖的长度cov
    //横坐标为x的情况下,纵坐标区间标记和
    ll cov[M<<2],sm[M<<2];
    void pu(int o,int l,int r){//向上计算结果
        if(cov[o]){
            sm[o]=li[r]-li[l-1];
        }else if(l==r){
            sm[o]=0;
        }else{
            sm[o]=sm[ls]+sm[rs];
        }
    }
    void up(int o,int l,int r,int x,int y,int d){//区间更新
        if(x<=l&&r<=y){
            cov[o]+=d;//由于我们最后只要全体区间的,没必要下移标记,从下往上递推即可,即过程长度可能不对,但整体区间一定是对的。
            pu(o,l,r);
            return ;
        }
        int m=(l+r)/2;
        if(x<=m)up(ls,l,m,x,y,d);
        if(y>m)up(rs,m+1,r,x,y,d);
        pu(o,l,r);
    }

    ll rectangleArea(vector<vector<int>>& re) {
        int nm=re.size();
        n=0;
        for(int i=0;i<nm;i++){
            int x1=re[i][0],y1=re[i][1],x2=re[i][2],y2=re[i][3];
            li.push_back(y1),li.push_back(y2);
            line[++n]=LINE{x1,y1,y2,1};
            line[++n]=LINE{x2,y1,y2,-1};
        }
        li.push_back(0);
        sort(line+1,line+1+n);
        sort(li.begin(),li.end());
        unique(li.begin(),li.end());
        ll ans=0;
        int sz=li.size()-1;
        for(int i=1;i<=n;i++){
            if(i>1 && line[i].x!=line[i-1].x){//开始计算面积
                ans=(ans+(line[i].x-line[i-1].x)*sm[1]%mod)%mod;
            }
            int y1=lower_bound(li.begin(),li.end(),line[i].y1)-li.begin(),
                y2=lower_bound(li.begin(),li.end(),line[i].y2)-li.begin();
            up(1,1,sz,y1+1,y2,line[i].op);
        }
        return ans;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值