社区讨论

线段树6倍空间

P5490【模板】扫描线 & 矩形面积并参与者 4已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@mhj0fozr
此快照首次捕获于
2025/11/03 18:41
4 个月前
此快照最后确认于
2025/11/03 18:41
4 个月前
查看原帖
经自测,线段树大概要开到6倍,八倍肯定是可以通过,求解释线段树使用空间
CPP
#include<iostream>
#include<algorithm>
using namespace std;
long long pos[200005];
struct Node
{
    long long l;
    long long r;
    long long x;
    long long flag;
}line[200005];
struct node
{
    long long l;
    long long r;
    long long cnt;
    long long len;
}t[600005];
long long len;
bool cmp(Node a,Node b)
{
    if(a.x==b.x) return a.flag<b.flag;
    return a.x<b.x;
}
void build(int p,int l,int r)
{
    t[p].l=l,t[p].r=r;
    if(l==r) return ;
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    return ;
}
void pushup(int p)
{
    if(t[p].cnt>0) t[p].len=pos[t[p].r+1]-pos[t[p].l];
    else
    {
        if(t[p].l==t[p].r) t[p].len=0;
        else t[p].len=t[p*2].len+t[p*2+1].len;
    }
    return ;
}
void update(int p,int l,int r,int d)
{
    if(t[p].l>=l&&t[p].r<=r)
    {
        t[p].cnt+=d;
        pushup(p);
        return;
    }
    int mid=(t[p].l+t[p].r)/2;
    if(l<=mid) update(p*2,l,r,d);
    if(r>mid) update(p*2+1,l,r,d);
    pushup(p);
    return ;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        long long x,y,xx,yy;
        cin>>x>>y>>xx>>yy;
        if(x>xx) swap(x,xx);
        if(y>yy) swap(y,yy);
        pos[i*2-1]=y,pos[i*2]=yy;
        line[i*2-1]={y,yy,x,1},line[i*2]={y,yy,xx,-1};
    }
    sort(pos+1,pos+2*n+1);
    int cnt=unique(pos+1,pos+2*n+1)-(pos+1);
    sort(line+1,line+2*n+1,cmp);
    build(1,1,cnt-1);
    long long ans=0;
    for(int i=1;i<2*n;i++)
    {
        int l=lower_bound(pos+1,pos+cnt+1,line[i].l)-pos;
        int r=lower_bound(pos+1,pos+cnt+1,line[i].r)-pos;
        if(l<r) update(1,l,r-1,line[i].flag);
        ans+=t[1].len*(line[i+1].x-line[i].x);
    }
    cout<<ans;
    return 0;
}

回复

4 条回复,欢迎继续交流。

正在加载回复...