【扫描线】Gym - 101982 - F - Rectangles

题目链接


题意:

给出若干个矩形,求出被奇数个矩形覆盖的面积。


题解:

题目很类似于扫描线的矩形面积并,联想一下那题的做法:把一个矩形拆成两条线段,赋值1和-1,代表入边和出边。对所有线段排序,在线段树上维护值为正数的大小。

本题是要求奇数,所以线段树应该维护的是值为奇数的大小。再仔细观察一下,对于一段区间添加了一条边,原来是偶数的变成了奇数,原来是奇数的变成了偶数,所以就相当于答案取反。

在此基础上设立lazy标记,标记这段区间被覆盖的奇偶次数,这样如果是偶数次那也不用向下pushdown了。


#include
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+7;
struct Edge{
    int x;
    int dw,up;
    bool operator<(const Edge k)const{
        return x>1;
        t[rt<<1]=y[m]-y[l]-t[rt<<1];
        t[rt<<1|1]=y[r]-y[m]-t[rt<<1|1];
        lz[rt<<1]^=1;
        lz[rt<<1|1]^=1;
        lz[rt]=0;
    }
}
void upd(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        t[rt]=y[r]-y[l]-t[rt];
        lz[rt]^=1;
        return;
    }
    if(r-l==1) return;
    pd(rt,l,r);
    int m=l+r>>1;
    if(L<=m) upd(rt<<1,l,m,L,R);
    if(m<=R) upd(rt<<1|1,m,r,L,R);
    t[rt]=t[rt<<1]+t[rt<<1|1];
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d%d",&lx[i],&ly[i],&rx[i],&ry[i]);
        y[++ty]=ly[i],y[++ty]=ry[i];
    }
    sort(y+1,y+1+ty);
    ty=unique(y+1,y+1+ty)-y-1;
    for(int i=1;i<=n;i++){
        int dw=lower_bound(y+1,y+1+ty,ly[i])-y;
        int up=lower_bound(y+1,y+1+ty,ry[i])-y;
        if(dw>up) swap(dw,up);
        e[++tot]=(Edge){lx[i],dw,up};
        e[++tot]=(Edge){rx[i],dw,up};
    }
    ll ans=0;
    sort(e+1,e+1+tot);
    for(int i=1;i<=tot;i++){
        ans+=1ll*(e[i].x-e[i-1].x)*t[1];
        upd(1,1,ty,e[i].dw,e[i].up);
    }
    printf("%lld\n",ans);
}

 

你可能感兴趣的:(数据结构)