Gym - 101982F 扫描线+线段树

Gym - 101982F 扫描线+线段树Gym - 101982F 扫描线+线段树Gym - 101982F 扫描线+线段树

           Gym - 101982F 扫描线+线段树

要你求覆盖奇数次的矩形面积并,每次更新时减去原先的值即可实现奇数次有效,下推时为保证线段长度不变左儿子的值为x[mid]-x[l]再减原来的值,右儿子的值为x[r]-x[mid]再减原来的值

#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define maxn 200005
struct seg{
    ll l,r,h,s;
    seg(){}
    seg(ll l,ll r,ll h,ll s):l(l),r(r),h(h),s(s){};
    bool operator <(const seg &a)const{
        return h<a.h;
    }
}se[maxn];
ll sum[maxn<<2],lazy[maxn<<2],x[maxn];
void pushup(ll rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(ll rt,ll l,ll r)
{
    if(lazy[rt])
    {
        lazy[rt<<1]^=1;
        lazy[rt<<1|1]^=1;
        ll mid=l+r>>1;
        sum[rt<<1]=x[mid]-x[l]-sum[rt<<1];
        sum[rt<<1|1]=x[r]-x[mid]-sum[rt<<1|1];
        lazy[rt]=0;
    }
}
void update(ll L,ll R,ll l,ll r,ll rt)
{
    if(L<=l&&R>=r)
    {
        lazy[rt]^=1;
        sum[rt]=x[r]-x[l]-sum[rt];
        return ;
    }
    ll mid=l+r>>1;
    pushdown(rt,l,r);
    if(L<mid)update(L,R,l,mid,rt<<1);
    //因为往右更新时是mid到r 不是mid+1到r 所以L<=mid 会造成死循环 如l=l r=2 L=2 R=3 mid=1
    if(R>mid)update(L,R,mid,r,rt<<1|1);
    pushup(rt);
}
int main()
{
    int n,x1,x2,y1,y2,tot=1;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x1>>y1>>x2>>y2;
        x[tot]=x1;
        se[tot++]=seg(x1,x2,y1,1);
        x[tot]=x2;
        se[tot++]=seg(x1,x2,y2,-1);
    }
    x[0]=-1;
    sort(x+1,x+tot);
    sort(se+1,se+tot);
    int nx=unique(x,x+tot)-x;
    ll ans=0;
    for(int i=1;i<tot-1;i++)
    {
        ll l=lower_bound(x,x+nx,se[i].l)-x;
        ll r=lower_bound(x,x+nx,se[i].r)-x;
        update(l,r,1,nx,1);
        ans+=sum[1]*(se[i+1].h-se[i].h);
    }
    cout<<ans<<endl;
    return 0;
}

 

上一篇:线段树求面积并,面积交,周长


下一篇:Tensorflow使用LSTM实现中文文本分类(二)