题解 P5490 【【模板】扫描线】

题解

看了怎么多题解,竟然没有一篇是下传标记的。

我来写一份常规的下传标记的做法。

我们需要维护区间最小值和最小值的个数

对于一个询问,如果区间最小值>0,那么返回区间长长度,否则说明区间有些地方是0,那么答案就是区间长度-最小值个数(长度)

然后就是普通线段树操作了,不需要标记用优化。

代码

#include<bits/stdc++.h>
using namespace std;
#define next Next
#define last Last
#define int long long
const int N=1e6+5;
int n,gs,len,b[N],mi[N*4],lazy[N*4],sum[N*4],Len[N*4];
struct node{
    int val,l,r,opt;
}a[N];
/*char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}*/
#define gc getchar
inline int read()
{
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}
void pushup(int nod)
{
    mi[nod]=min(mi[nod*2],mi[nod*2+1]);
    if(mi[nod]==mi[nod*2])sum[nod]=sum[nod*2];
    else sum[nod]=0;
    if(mi[nod]==mi[nod*2+1])sum[nod]+=sum[nod*2+1];
}
void pushdown(int nod)
{
    if(lazy[nod]==0)return;
    mi[nod*2]+=lazy[nod];
    mi[nod*2+1]+=lazy[nod];
    lazy[nod*2]+=lazy[nod];
    lazy[nod*2+1]+=lazy[nod];
    lazy[nod]=0;   
}
void build(int nod,int l,int r)
{
    Len[nod]=b[r+1]-b[l];
    if(l==r)
    {
        sum[nod]=Len[nod];
        return;
    }
    int mid=(l+r)/2;
    build(nod*2,l,mid);
    build(nod*2+1,mid+1,r);
    pushup(nod);
}
void change(int nod,int l,int r,int L,int R,int val)
{
    if(l==L&&r==R)
    {
        mi[nod]+=val;
        lazy[nod]+=val;
        return;
    }
    pushdown(nod);
    int mid=(l+r)/2;
    if(R<=mid)change(nod*2,l,mid,L,R,val);
    else if(L>mid)change(nod*2+1,mid+1,r,L,R,val);
    else{
        change(nod*2,l,mid,L,mid,val);
        change(nod*2+1,mid+1,r,mid+1,R,val);
    }
    pushup(nod);
}
int find(int nod,int l,int r,int L,int R)
{
    if(l==L&&r==R)
    {
        if(mi[nod]>0)return Len[nod];
        return Len[nod]-sum[nod];
    }
    pushdown(nod);
    int mid=(l+r)/2;
    if(R<=mid)return find(nod*2,l,mid,L,R);
    else if(L>mid)return find(nod*2+1,mid+1,r,L,R);
    else return find(nod*2,l,mid,L,mid)+find(nod*2+1,mid+1,r,mid+1,R);
    pushup(nod);
}
bool cmp(node a,node b)
{
    return a.val<b.val;
}
signed main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        int x1=read(),y1=read(),x2=read(),y2=read();
        a[++gs]=(node){x1,y1,y2,1};
        a[++gs]=(node){x2,y1,y2,-1};
        b[++len]=y1;
        b[++len]=y2;
    }
    sort(b+1,b+len+1);
    len=unique(b+1,b+len+1)-b-1;
    build(1,1,len-1);
    for(int i=1;i<=gs;i++)
    {
        a[i].l=lower_bound(b+1,b+len+1,a[i].l)-b;
        a[i].r=lower_bound(b+1,b+len+1,a[i].r)-b;
    }
    sort(a+1,a+gs+1,cmp);
    int ans=0;
    for(int i=1;i<gs;i++)
    {
        if(a[i].l<a[i].r)change(1,1,len-1,a[i].l,a[i].r-1,a[i].opt);
        ans=ans+find(1,1,len-1,1,len-1)*(a[i+1].val-a[i].val);
    }
    cout<<ans;
}