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

题面:http://codeforces.com/gym/101982/attachments/download/7897/20182019-acmicpc-pacific-northwest-regional-contest-div-1-en.pdf

 

题意:给出n个矩形的位置,问重叠奇数个矩形的面积之和

 

做法:

      和一般的线段树不一样,要将原来的[l,mid],[mid+1,r],改成[l,mid],[mid,r],这样才不能改变其总长度。用线段树做一下区间更新即可。记住打laz标记。

 

#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long ll;
const int maxn=100005;
struct seg{
    ll l,r,h;
}se[maxn*2];
ll siz[maxn*8];
bool laz[maxn*8];
bool cmp(seg a,seg b){
    return a.h<b.h;
}
ll n,k,m,X[maxn*2];
ll fin(ll x){
    ll ans=lower_bound(X,X+m,x)-X;
    return ans;
}
void Switch(ll l,ll r,ll rt){
    ll all=X[r]-X[l];
    siz[rt]= all-siz[rt];
}
void pushdown(ll l,ll r,ll rt){
    if(laz[rt]){
        ll mid=(l+r)/2;
        Switch(l,mid,lson);
        Switch(mid,r,rson);
        laz[lson]^=1; laz[rson]^=1;
        laz[rt]=0;
    }
}
void update(ll ql,ll qr,ll l,ll r,ll rt){
    if(l>=ql&&r<=qr){
        Switch(l,r,rt);
        laz[rt]^=1;
        return ;
    }
    pushdown(l,r,rt);
    ll mid=(l+r)/2;
    if(ql<mid) update(ql,qr,l,mid,lson);
    if(qr>mid) update(ql,qr,mid,r,rson);
    siz[rt]=siz[lson]+siz[rson];
}
int main(){

        scanf("%d",&n);
        k=1;
        for(int i=1;i<=n;i++,k+=2){
            ll x1,x2,y1,y2;
            scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
            X[k]=x1,X[k+1]=x2;
            se[k].l=x1,se[k].r=x2,se[k].h=y1;
            se[k+1].l=x1,se[k+1].r=x2,se[k+1].h=y2;
        }
        k--;
        X[0]=-1;
        sort(se+1,se+1+k,cmp);
        sort(X+1,X+1+k);
        m=0;
        for(int i=1;i<=k;i++){
            if(X[i]!=X[i-1]) X[++m]=X[i];
        }
        ll ans=0;
        for(int i=1;i<k;i++){
            int l=fin(se[i].l);
            int r=fin(se[i].r);
            update(l,r,1,m,1);
            ans=(ans+siz[1]*(se[i+1].h-se[i].h));
            //printf("i=%d ans=%.2f\n",i,ans);
        }
        printf("%lld\n",ans);


    return 0;
}

 

 

poj 2482 http://poj.org/problem?id=2482

同样的左闭右开区间。累的啊。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lson rt<<1
#define rson rt<<1|1
typedef long long ll;
using namespace std;
const int maxn=10005;
struct seg{
    ll l,r,h,v;
    seg(){}
    seg(ll l,ll r,ll h,ll v):l(l),r(r),h(h),v(v){}
    bool operator < (const seg &a)const{
        if(a.h==h) return v<a.v;
        return h<a.h;
    }
} se[maxn*2];
int n,m;
ll H,W;
ll sum[maxn<<3],laz[maxn<<3],X[maxn*2];
void deal(int rt,ll v){
    sum[rt]+=v;
    laz[rt]+=v;
}
void push_down(int rt){
    if(laz[rt]){
        deal(lson,laz[rt]);
        deal(rson,laz[rt]);
        laz[rt]=0;
    }
}
void update(int ql,int qr,int l,int r,int rt,ll v){
    if(ql<=l&&r<=qr){
        deal(rt,v);
        return ;
    }
    push_down(rt);
    int mid=(l+r)/2;
    if(ql<mid) update(ql,qr,l,mid,lson,v);
    if(qr>mid) update(ql,qr,mid,r,rson,v);
    sum[rt]=max(sum[lson],sum[rson]);
}
int main(){
    while(~scanf("%d%lld%lld",&n,&W,&H)){
        memset(sum,0,sizeof(sum));
        memset(laz,0,sizeof(laz));
        rep(i,1,n){
            ll xx,yy,bri;
            scanf("%lld%lld%lld",&xx,&yy,&bri);
            se[i]=seg(xx,xx+W,yy,bri);
            se[i+n]=seg(xx,xx+W,yy+H,-bri);
            X[i]=xx,X[i+n]=xx+W;
        }
        n*=2;
        sort(se+1,se+1+n);
        sort(X+1,X+1+n);
        m=unique(X+1,X+1+n)-X-1;

        ll ans=0;

        rep(i,1,n){
            int L=lower_bound(X+1,X+1+m,se[i].l)-X;
            int R=lower_bound(X+1,X+1+m,se[i].r)-X;
            update(L,R,1,m,1,se[i].v);
            ans=max(ans,sum[1]);
        }
        printf("%lld\n",ans);
    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值