Luogu P5490 扫描线

模板题,想象一条线从左边扫到右边,只有在矩阵边界才会产生影响,所以我们离散化缩小数据范围,再用线段树维护扫描线上的情况,得出结果

#include<bits/stdc++.h>
#define ls k<<1
#define rs k<<1|1
#define int long long//注意要开longlong
using namespace std;
const int N=1e6+5;
int val[N<<1];
struct Seg_Tree{
    int l,r,sum,cnt;
}tr[N<<2];
inline void build(int k,int l,int r){
    tr[k].l=l,tr[k].r=r;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
}
inline void pushup(int k){
    if(tr[k].cnt) tr[k].sum=val[tr[k].r+1]-val[tr[k].l];
    else tr[k].sum=tr[ls].sum+tr[rs].sum;//下传标记
}
inline void add(int k,int x,int y,int v){
    if(tr[k].l>y||tr[k].r<x)return;
    if(x<=tr[k].l&&tr[k].r<=y){
        tr[k].cnt+=v;
        pushup(k);
        return;
    }
    add(ls,x,y,v);
    add(rs,x,y,v);
    pushup(k);
}
int n,cnt,tot,book[N<<2];
struct node{
    int x,yl,yr,flag;
}e[N<<1];
bool cmp(node a,node b){return a.x<b.x||(a.x==b.x&&a.flag>b.flag);}
signed main(){
    scanf("%lld",&n);
    for(int i=1,xl,xr,yl,yr;i<=n;i++){
        scanf("%lld%lld%lld%lld",&xl,&yl,&xr,&yr);
        book[++cnt]=yl;book[++cnt]=yr;
        e[++tot].x=xl;e[tot].yl=yl;e[tot].yr=yr;e[tot].flag=1;
        e[++tot].x=xr;e[tot].yl=yl;e[tot].yr=yr;e[tot].flag=-1;//离散化
    }
    sort(book+1,book+cnt+1);
    int h=unique(book+1,book+cnt+1)-book-1;
    for(int i=1;i<=tot;i++){
        int pos1=lower_bound(book+1,book+h+1,e[i].yl)-book;
        int pos2=lower_bound(book+1,book+h+1,e[i].yr)-book;
        val[pos1]=e[i].yl;val[pos2]=e[i].yr;
        e[i].yl=pos1;e[i].yr=pos2;//记录
    }
    sort(e+1,e+tot+1,cmp);
    build(1,1,tot);
    int ans=0;
    for(int i=1;i<=tot;i++){
        add(1,e[i].yl,e[i].yr-1,e[i].flag);
        ans+=tr[1].sum*(e[i+1].x-e[i].x);//得出答案
    }
    cout<<ans<<endl;
}

 

posted @ 2019-08-18 20:52  Coder_cjh  阅读(147)  评论(0编辑  收藏  举报