扫描线 & 矩形面积并

code on 26.7.16

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define lson (rt<<1)
#define rson (rt<<1|1)
using namespace std;
constexpr int maxn=2e6+10,p=1e9+7;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0' || ch>'9')
    {
        if (ch == '-') f=-1;
        ch=getchar();
    }
    while (ch>='0' && ch<='9')
    {
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
struct _
{
    int xa,xb,y,b;
    bool operator < (_ a) const {return y<a.y;}
}lin[maxn];
struct __ {int l,r,sum,cnt;}tr[maxn];
int lc,cnt,n,ans,a[maxn],xa,xb,ya,yb;
void Pushup(int rt)
{
    if (tr[rt].cnt) tr[rt].sum=a[tr[rt].r+1]-a[tr[rt].l];
    else tr[rt].sum=tr[lson].sum+tr[rson].sum;
}
void Build(int rt,int l,int r)
{
    tr[rt].l=l,tr[rt].r=r;
    if (l == r) return;
    int mid=(l+r) >> 1;
    Build(lson,l,mid),Build(rson,mid+1,r);
}
void Upd(int rt,int l,int r,int val)
{
    if (l<=tr[rt].l && tr[rt].r<=r)
    {
        tr[rt].cnt+=val;
        Pushup(rt);
        return;
    }
    int mid=(tr[rt].l+tr[rt].r) >> 1;
    if (l<=mid) Upd(lson,l,r,val);
    if (r>mid) Upd(rson,l,r,val);
    Pushup(rt);
}
signed main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        xa=read(),ya=read(),xb=read(),yb=read();
        lc++;lin[lc]={xa,xb,ya,0};
        lc++;lin[lc]={xa,xb,yb,1};
        a[i]=xa,a[i+n]=xb;
    }
    sort(a+1,a+1+n*2);
    cnt=unique(a+1,a+1+n*2)-a-1;
    sort(lin+1,lin+1+n*2);
    Build(1,1,cnt-1);
    for (int i=1;i<=n*2;i++)
    {
        _ l=lin[i];
        if (i>1) ans+=tr[1].sum*(lin[i].y-lin[i-1].y);
        if (l.b)
        {
            int u,v;
            u=lower_bound(a+1,a+1+cnt,l.xa)-a;
            v=lower_bound(a+1,a+1+cnt,l.xb)-a-1;
            Upd(1,u,v,-1);
        }
        else
        {
            int u,v;
            u=lower_bound(a+1,a+1+cnt,l.xa)-a;
            v=lower_bound(a+1,a+1+cnt,l.xb)-a-1;
            Upd(1,u,v,1);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

## code(展示从上往下扫,从左往右扫同理) ```c++ #include using namespace std; #define lson (rt << 1) #define rson (rt << 1 | 1) struct lline { long long xa,xb,y; bool b; bool operator<(lline a)const { return y> 1; build(lson,l,mid); build(rson,mid+1,r); } void update(int rt,int l,int r,int val) { if (l<=tree[rt].l && tree[rt].r<=r) { tree[rt].cnt += val;//这个是更新被覆盖的次数的 pushup(rt);//这个是更新被覆盖的次数的 return; } int mid = (tree[rt].l+tree[rt].r) >> 1; if (l<=mid) update(lson,l,r,val); if (r>mid) update(rson,l,r,val); pushup(rt); } int main() { cin >> n; for (int i=1;i<=n;i++) { cin >> xa >> ya >> xb >> yb; //先插入一条线段 line[++lc].xa=xa; line[lc].xb=xb; line[lc].y = ya; line[lc].b=false; //再撤销一条线段 line[++lc].xa=xa; line[lc].xb=xb; line[lc].y = yb; line[lc].b=true; //离散化 a[i]=xa; a[i+n]=xb; } sort(a+1,a+1+n*2);//由于n是正方体数,所以要*2 cnt = unique(a+1,a+1+n*2)-a-1; //离散化 sort(line+1,line+1+n*2); //扫描线一定是一个有序的处理过程,在某个点把与该点有关的全部改好 //所以记得先排个序 build(1,1,cnt-1);//由于在pushup中+1了,所以这里也要-1 for (int i=1;i<=n*2;i++) { lline l = line[i]; if (i>1) ans += tree[1].sum*(line[i].y-line[i-1].y); if (l.b) { int u,v; u = lower_bound(a+1,a+1+cnt,l.xa)-a; v = lower_bound(a+1,a+1+cnt,l.xb)-a-1;//由于会出现扫到点的情况(如[3,3]),-1就能避免 update(1,u,v,-1);//-1即为撤销 } else { int u,v; u = lower_bound(a+1,a+1+cnt,l.xa)-a; v = lower_bound(a+1,a+1+cnt,l.xb)-a-1;//-1同上 update(1,u,v,1);//1即为增加 } } cout << ans < using namespace std; typedef long long ll; const int maxn=2e5+10; #define lson v[rt].ls #define rson v[rt].rs ll n,root,tot,y[maxn],val[maxn],sum,ans; struct mcx { ll x=0,y1=0,y2=0; bool in=0; }v1[maxn]; bool cmp(mcx x,mcx y) { return x.x>1; if(x<=val[mid]) { ans=mid; t=mid-1; } else h=mid+1; } return ans; } void pushup(ll rt,ll l,ll r) { if(v[rt].cnt) v[rt].len=val[r+1]-val[l]; else v[rt].len=v[lson].len+v[rson].len; } void update(ll &rt,ll l,ll r,ll L,ll R,ll k) { if(!rt) rt=++tot; if(l>=L&&r<=R) { v[rt].cnt+=k; pushup(rt,l,r); return; } ll mid=(l+r)>>1; if(L<=mid) update(lson,l,mid,L,R,k); if(R>mid) update(rson,mid+1,r,L,R,k); pushup(rt,l,r); } int main () { cin>>n; for(int i=1;i<=n;i++) { int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; v1[i].x=x1;v1[i].y1=y1;v1[i].y2=y2;v1[i].in=true; v1[i+n].x=x2;v1[i+n].y1=y1;v1[i+n].y2=y2;v1[i+n].in=false; y[i]=y1; y[i+n]=y2; } stable_sort(y+1,y+1+2*n); stable_sort(v1+1,v1+1+2*n,cmp); for(int i=1;i<=2*n;i++) if(y[i]!=y[i-1]) val[++sum]=y[i]; for(int i=1;i<=2*n;i++) { // cout< using namespace std;

define lson (rt<<1)

define rson (rt<<1|1)

define int long long

const int N = 2e6+10;
typedef long long ll;

inline void read(int &x)//加速输入
{
char ch=getchar();int f=1;x=0;
while(!isdigit(ch) && ch^'-') ch=getchar();
if(ch=='-') f=-1,ch=getchar();
while(isdigit(ch)) x=x10+ch-'0',ch=getchar();
x
=f;
}

struct smx{
int y1,y2,x,cnt;
bool aaa;
}line[N];

bool cmp(smx a,smx b){
return a.x < b.x;
}
int a[N];
struct node{
int l,r,len,cnt;
}tr[N];

void build(int rt,int l,int r){
tr[rt].l=l,tr[rt].r=r;
if(l==r) return;
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
}

void pushup(int rt){
if(tr[rt].cnt) tr[rt].len=a[tr[rt].r+1]-a[tr[rt].l];
else tr[rt].len = tr[lson].len + tr[rson].len;
}

void update(int rt,int l,int r,int k){
if(l<=tr[rt].l && r>=tr[rt].r) {
tr[rt].cnt+=k;
pushup(rt);
return;
}

int mid=(tr[rt].l+tr[rt].r)>>1;
if(mid>=l) update(lson,l,r,k);
if(r>mid) update(rson,l,r,k);
pushup(rt);
}

int n,ans;

signed main(){

//输入
cin >> n;
int x1,y1,x2,y2,op=0;
for(int i=1;i<=n;i++){
cin >> x1 >> y1 >> x2 >> y2;
line[++op].x = x1;
line[op].y1 = y1;
line[op].y2 = y2;
line[op].aaa = 0;
line[++op].x = x2;
line[op].y1 = y1;
line[op].y2 = y2;
line[op].aaa = 1;
a[i]=y1;
a[i+n]=y2;
}

//离散化
sort(a+1,a+1+n2);
int cnt = unique(a+1,a+1+2
n)-a-1;
sort(line+1,line+1+2*n,cmp);
build(1,1,cnt);

//开始骚妙
for(int i=1;i<=n<<1;i++) {
if(i>1) ans+=tr[1].len*(line[i].x-line[i-1].x);

if(line[i].aaa) update(1,lower_bound(a+1,a+1+cnt,line[i].y1)-a,lower_bound(a+1,a+1+cnt,line[i].y2)-a-1,-1);
else update(1,lower_bound(a+1,a+1+cnt,line[i].y1)-a,lower_bound(a+1,a+1+cnt,line[i].y2)-a-1,1);
}
cout << ans;
return 0;
}

## 注
- 注释来源于老学长_2K22_
posted @ 2026-03-24 11:42  msjing  阅读(8)  评论(0)    收藏  举报