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;
}
};