腐女的生日

题目描述

腐女要过生日了,pty 想给腐女送礼物,但是腐女所在的教室离pty 的教室太远了,于是pty就拜托会动归和A星的djy帮忙送礼物。djy在学校建立了一个平面直角坐标系,他站在了(0,0)点,腐女在(x0,y0)点,djy每次只能往上下左右四个方向移动一步,中间有n栋矩形教学楼,每个教学楼给出两个对角的坐标,并且保证每栋教学楼的周围区域(如图所示)不会有别的教学楼,即djy可以绕一个教学楼走不会碰到任何障碍,现在djy 想知道从起点到终点不碰到任何教学楼,最短需要多少步。

扫描线

除了第一步会左走
其余情况均不会左走。
用扫描线保存当前x坐标下到每点的最短路。
遇到矩形边界时讨论一下。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100000+10,mx=1000002,maxm=2000003;
int sx[maxm*4+100],gc[maxm*4+100];
bool bz[maxm*4+100],pd[maxm*4+100];
struct dong{
    int x,ca,y0,y1;
} ask[maxn*2];
int i,j,k,l,r,t,n,m,tot,top,x,x0,y0,x1,y1,x2,y2,ans;
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*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
bool cmp(dong a,dong b){
    return a.x<b.x||a.x==b.x&&a.ca>b.ca;
}
void markad(int p,int v,int d){
    if (pd[p]) return;
    sx[p]+=v;
    gc[p]+=d;
}
void markcl(int p){
    bz[p]=1;
    sx[p]=gc[p]=0;
}
void down(int p,int l,int r){
    int mid=(l+r)/2;
    if (bz[p]){
        markcl(p*2);
        markcl(p*2+1);
        bz[p]=0;
    }
    if (sx[p]||gc[p]){
        markad(p*2,sx[p],gc[p]);
        markad(p*2+1,sx[p]+(mid-l+1)*gc[p],gc[p]);
        sx[p]=gc[p]=0;
    }
}
void change(int p,int l,int r,int a,int b,int v,int d){
    if (pd[p]||a>b) return;
    if (l==a&&r==b){
        markad(p,v,d);
        return;
    }
    down(p,l,r);
    int mid=(l+r)/2;
    if (b<=mid) change(p*2,l,mid,a,b,v,d);
    else if (a>mid) change(p*2+1,mid+1,r,a,b,v,d);
    else{
        change(p*2,l,mid,a,mid,v,d);
        change(p*2+1,mid+1,r,mid+1,b,v+d*(mid-a+1),d);
    }
}
void clear(int p,int l,int r,int a,int b,int v){
    if (l==a&&r==b){
        pd[p]=v;
        if (v) markcl(p);
        return;
    }
    down(p,l,r);
    int mid=(l+r)/2;
    if (b<=mid) clear(p*2,l,mid,a,b,v);
    else if (a>mid) clear(p*2+1,mid+1,r,a,b,v);
    else{
        clear(p*2,l,mid,a,mid,v);
        clear(p*2+1,mid+1,r,mid+1,b,v);
    }
}
int query(int p,int l,int r,int a){
    if (l==r) return sx[p];
    down(p,l,r);
    int mid=(l+r)/2;
    if (a<=mid) return query(p*2,l,mid,a);else return query(p*2+1,mid+1,r,a);
}
int main(){
    freopen("bl.in","r",stdin);freopen("bl.out","w",stdout);
    x0=read();y0=read();
    ask[top=1].x=x0;ask[1].y0=y0;
    n=read();
    fo(i,1,n){
        x1=read();y1=read();x2=read();y2=read();
        if (x1>x2){
            swap(x1,x2);
            swap(y1,y2);
        }
        if (y1>y2) swap(y1,y2);
        ask[++top].x=x1;
        ask[top].ca=1;
        ask[top].y0=y1;ask[top].y1=y2;
        ask[++top].x=x2+1;
        ask[top].ca=2;
        ask[top].y0=y1;ask[top].y1=y2;
    }
    sort(ask+1,ask+top+1,cmp);
    x=0;
    change(1,1,maxm,mx+1,maxm,1,1);
    change(1,1,maxm,1,mx-1,mx-1,-1);
    fo(i,1,top){
        change(1,1,maxm,1,maxm,ask[i].x-x,0);
        x=ask[i].x;
        if (ask[i].ca==0){
            ans=query(1,1,maxm,ask[i].y0+mx);
            break;
        }
        else if (ask[i].ca==1){
            clear(1,1,maxm,ask[i].y0+mx,ask[i].y1+mx,1);
        }
        else if (ask[i].ca==2){
            clear(1,1,maxm,ask[i].y0+mx,ask[i].y1+mx,0);
            j=query(1,1,maxm,ask[i].y0-1+mx);
            k=query(1,1,maxm,ask[i].y1+1+mx);
            l=ask[i].y1-ask[i].y0+1;
            t=(k+l+1-j)/2;
            if (t<1) change(1,1,maxm,ask[i].y0+mx,ask[i].y1+mx,k+l,-1);
            else if (t>l) change(1,1,maxm,ask[i].y0+mx,ask[i].y1+mx,j+1,1);
            else{
                change(1,1,maxm,ask[i].y0+mx,ask[i].y0+t-1+mx,j+1,1);
                change(1,1,maxm,ask[i].y0+t+mx,ask[i].y1+mx,k+l-t,-1);
            }
        }
    }
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值