zoukankan      html  css  js  c++  java
  • #zkw线段树,扫描线,dp,离散#NOIP2020.9.26模拟speike

    题目


    分析

    由于可以走边界,那么最短路径一定按横坐标递增并且经过矩形的顶点,
    考虑扫描线,找到当前线段(矩形右边界可以忽略)两个端点离的最近而又可达的线段,
    dp一下并用线段树维护就可以了


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=500011;
    typedef long long lll; lll dp[N][2];
    struct duan{int x,l,r;}line[N];
    int w[N<<2],xt,q,b[N<<1],bas,n,m;
    inline signed iut(){
    	rr int ans=0,f=1; rr char c=getchar();
    	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans*f;
    }
    bool cmp(duan x,duan y){return x.x<y.x;}
    inline signed max(int a,int b){return a>b?a:b;}
    inline lll min(lll a,lll b){return a<b?a:b;}
    inline signed aabs(int x){return x<0?-x:x;}
    inline signed query(int x){
    	rr int ans=1;
    	for (x+=bas;x;x>>=1)
    	    ans=max(ans,w[x]);
    	return ans;
    }
    inline void update(int l,int r,int z){
    	for(l+=bas-1,r+=bas+1;l^r^1;l>>=1,r>>=1){
    		if (!(l&1)) w[l^1]=max(w[l^1],z);
    		if (r&1) w[r^1]=max(w[r^1],z);
    	}
    }
    signed main(){
    	freopen("speike.in","r",stdin);
    	freopen("speike.out","w",stdout);
    	n=iut(),m=1,line[1]=(duan){0,0,0},
    	line[2]=(duan){xt=iut(),0,0},q=2;
    	for (rr int i=1;i<=n;++i){
    		rr int lx=iut(),ly=iut(),rx=iut(),ry=iut();
    		if (lx>rx) swap(lx,rx); if (ly>ry) swap(ly,ry);
    		line[++q]=(duan){lx,ly,ry},b[++m]=ly,b[++m]=ry;
    	}
    	sort(b+1,b+1+m),m=unique(b+1,b+1+m)-b-1;
    	sort(line+2,line+1+q,cmp);
    	for (bas=1;(bas<<=1)<m+3;);
    	for (rr int i=1;i<=q;++i)
    		line[i].l=lower_bound(b+1,b+1+m,line[i].l)-b,
    		    line[i].r=lower_bound(b+1,b+1+m,line[i].r)-b;
    	for (rr int i=2;i<=q;++i){
    		rr int t1=query(line[i].l),t2=query(line[i].r);
    		dp[i][0]=min(dp[t1][0]+aabs(b[line[i].l]-b[line[t1].l]),dp[t1][1]+aabs(b[line[i].l]-b[line[t1].r])),
    		dp[i][1]=min(dp[t2][0]+aabs(b[line[i].r]-b[line[t2].l]),dp[t2][1]+aabs(b[line[i].r]-b[line[t2].r])),
    		update(line[i].l,line[i].r,i);
    	}
    	return !printf("%lld",min(dp[q][0],dp[q][1])+xt);
    } 
    
  • 相关阅读:
    单片机八位时钟
    共阴数码管断码与位码
    PCB自己做一个原理图模版
    Mongodb在Linux下的安装和启动和配置
    linux下用phpize给PHP动态添加扩展
    微信支付JS各种调试问题
    秒速插入百万测试数据MYSQL,提供你玩玩大数据!
    金子的PHP之禅(函数篇四)
    linux下面查找某个字符或者文件
    金子的PHP之禅(PHP运算符三)
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13817287.html
Copyright © 2011-2022 走看看