Codeforces 610D Vika and Segments

题目大意:给你n(n<=1e9)条垂直于x轴或者与x轴平行的线,问你这些线占了多少个点。

写的时候感觉就是一道线段树,可是想不出来,后来题解说可以转化成面积问题,就知道

怎么写了,是一道线段树加扫描线求面积并的问题。

思路:将一条线转化为宽度为1的矩形,然后用线段树+扫描线+离散化求面积并就行了,

顺便帮我复习了一下扫描线。。 以后要多想想怎么转化不能这么菜了!!!!

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
using namespace std;
const int N=2*1e5+3;
struct line
{
    int x,y1,y2,op;
    bool operator < (const line &t)const
    {
        if(x==t.x) return op<t.op;
        return x<t.x;
    }
}e[N];
int n,y[N],tot=0,cnt=0;
int seg[N<<2],cover[N<<2]; //seg[i] 表示i这个区域内的覆盖长度,cover表示覆盖了几次。
void push_up(int rt,int l,int r,int op)
{
    if(cover[rt]>=1) seg[rt]=y[r+1]-y[l];
    else if(l==r)
    {
        if(op==1) seg[rt]=y[r+1]-y[l];
        else seg[rt]=0;
    }
    else seg[rt]=seg[rt<<1]+seg[rt<<1|1];
}
void updata(int L,int R,int l,int r,int rt,int g)
{
    if(l>=L && r<=R)
    {
        cover[rt]+=g;
        push_up(rt,l,r,g);
        return;
    }
    int m=(l+r)>>1;
    if(L<=m) updata(L,R,lson,g);
    if(R>m) updata(L,R,rson,g);
    push_up(rt,l,r,g);
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        if(y1>y2) swap(y1,y2),swap(x1,x2);
        if(y1==y2)
        {
            e[tot].x=x1; e[tot].y1=y1; e[tot++].y2=y1+1;
            e[tot].x=x2; e[tot].y1=y1; e[tot++].y2=y1+1;
            y[cnt++]=y1; y[cnt++]=y1+1;
            if(x1>x2) e[tot-2].x+=1,e[tot-1].op=1,e[tot-2].op=-1;
            else e[tot-1].x+=1,e[tot-2].op=1,e[tot-1].op=-1;
        }
        else
        {
            e[tot].x=x1; e[tot].op=1; e[tot].y1=y1; e[tot++].y2=y2+1;
            e[tot].x=x1+1; e[tot].op=-1; e[tot].y1=y1; e[tot++].y2=y2+1;
            y[cnt++]=y1; y[cnt++]=y2+1;
            if(x1>x2) e[tot-1].op=1,e[tot-2].op=-1;
            else e[tot-1].op=-1,e[tot-2].op=1;
        }
    }
    sort(y,y+cnt); sort(e,e+tot);
    cnt=unique(y,y+cnt)-y;
    ll ans=0,pre=-1e18;
    for(int i=0;i<tot;i++)
    {
        if(pre!=-1e18) ans+=(ll)(e[i].x-pre)*(ll)seg[1];
        int up=lower_bound(y,y+cnt,e[i].y2)-y;
        int down=lower_bound(y,y+cnt,e[i].y1)-y;
        updata(down,up-1,0,tot-1,1,e[i].op);
        pre=e[i].x;
    }
    cout<<ans<<endl;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/CJLHY/p/7400409.html