K - Kingdom of Ants Kattis - kingdomofants

本文介绍了一种使用线段树和扫描线算法解决几何问题的方法,具体为求解多个矩形区域的面积交集。通过维护区间修改次数、区间次数为奇数和偶数的个数,算法能高效地计算出矩形区域相交部分的面积,适用于处理大量动态更新的几何数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解:线段树扫描线求面积交,维护区间修改次数为0的和区间次数为奇数和偶数的,偶数的个数减去为0的个数就是面积交为偶数个矩阵。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e6+100;
struct Line{
    ll y,x1,x2,v;
    bool operator < (const Line&p) const{
        return y<p.y;
    }
}line[maxn*4];

ll px[maxn*4];
ll tree[maxn*4],laz[maxn*4],len[maxn*4][2];
int filp[maxn*4];
void push_up(int x,int l,int r){
    if(laz[x]) tree[x]=px[r+1]-px[l];
    else if(l==r) tree[x]=0;
    else tree[x]=tree[x<<1]+tree[x<<1|1];
}

void add(int x,int l,int r,int lx,int rx,ll val){ //维护区间>0的个数
    if(lx<=l&&rx>=r){
        laz[x]+=val;
        push_up(x,l,r);
        return ;
    }
    int mid=(l+r)>>1;
    if(lx<=mid) add(x<<1,l,mid,lx,rx,val);
    if(rx>mid) add(x<<1|1,mid+1,r,lx,rx,val);
    push_up(x,l,r);
}

void push_down(int x){
    swap(len[x<<1][0],len[x<<1][1]);
    swap(len[x<<1|1][0],len[x<<1|1][1]);
    filp[x<<1]^=1; filp[x<<1|1]^=1;
    filp[x]=0;
}
void update(int x,int l,int r,int lx,int rx){ //维护区间为偶数的
    if(lx<=l&&rx>=r){
        filp[x]^=1;
        swap(len[x][0],len[x][1]);
        return ;
    }
    if(filp[x]) push_down(x);
    int mid=(l+r)>>1;
    if(lx<=mid) update(x<<1,l,mid,lx,rx);
    if(rx>mid)  update(x<<1|1,mid+1,r,lx,rx);
    len[x][0]=len[x<<1][0]+len[x<<1|1][0];
    len[x][1]=len[x<<1][1]+len[x<<1|1][1];
}

void build(int x,int l,int r){
    len[x][0]=px[r+1]-px[l];
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
}

int main(){

    int n,cnt=0,tot=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        ll a,b,c,d;
        scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
        if(a==c||b==d) continue;
        px[++tot]=a;  px[++tot]=c;
        line[++cnt]=Line{min(b,d),min(a,c),max(a,c),1};
        line[++cnt]=Line{max(b,d),min(a,c),max(a,c),-1};
    }
    if(!cnt) {
        cout<<0<<endl;
        return 0;
    }
    sort(line+1,line+1+cnt);
    sort(px+1,px+1+tot);
    tot=unique(px+1,px+1+tot)-(px+1); px[tot+1]=px[tot];
    build(1,1,tot); ll ans=0;
    for(int i=1;i<=cnt-1;i++){
        int x1=upper_bound(px+1,px+1+tot,line[i].x1)-(px+1);
        int x2=upper_bound(px+1,px+1+tot,line[i].x2)-(px+1)-1;
        update(1,1,tot,x1,x2);
        add(1,1,tot,x1,x2,line[i].v);
        ans+=(ll)(len[1][0]-(px[tot]-px[1]-tree[1]))*(ll)(line[i+1].y-line[i].y);
    }
    cout<<ans<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值