• POJ2374_Fence Obstacle Course


    题意是描述是这样的,给你n个围栏,对于每个围栏你必须走到其边上才可以往下跳,现在问你从初始最高位置的n个围栏,到原点,水平走过的路程最少是多少?

    其实我可可以这样来考虑问题。由于每次都是从板子的左右两端往下面跳,我们可以从1到n有序的加入每一块板子(相当于对区间染色),加入每块板子查询一下它的两端的下面的点是什么。有了这个操作我们就可以直接预处理出来从每一块板子左右两端跳下来会落在那一块板子上面。

    那应该用什么办法来实现这个查询和更新呢?显然,线段树。

    下面我们等于是分别从第n块板子的左右端点往下走,然后求到原点的水平最短路了,直接一遍SPFA搞定。

    上代码吧,下面省略若干个字。

     

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <queue>
      5 #define maxn 200100
      6 using namespace std;
      7 
      8 const int add=100005;
      9 int n,S,ans;
     10 int l[maxn],r[maxn],fl[maxn],fr[maxn],pl[maxn],pr[maxn];
     11 int a[4*maxn],col[4*maxn];
     12 bool inq[maxn];
     13 
     14 int abs(int x)
     15 {
     16     return x>=0?x:-x;
     17 }
     18 
     19 void PushDown(int rt)
     20 {
     21     if (col[rt]==-1) return;
     22     col[rt<<1]=col[rt<<1|1]=col[rt];
     23     col[rt]=-1;
     24 }
     25 
     26 void update(int rt,int l,int r,int L,int R,int id)
     27 {
     28     if (L<=l && R>=r)
     29     {
     30         col[rt]=id;
     31         return;
     32     }
     33     PushDown(rt);
     34     int mid=(l+r)>>1;
     35     if (L<=mid) update(rt<<1,l,mid,L,R,id);
     36     if (R> mid) update(rt<<1|1,mid+1,r,L,R,id);
     37 }
     38 
     39 int query(int rt,int l,int r,int pos)
     40 {
     41     if (l<=pos && r>=pos && col[rt]>=0) return col[rt];
     42     PushDown(rt);
     43     int mid=(l+r)>>1;
     44     if (pos<=mid) return query(rt<<1,l,mid,pos);
     45         else return query(rt<<1|1,mid+1,r,pos);
     46 }
     47 
     48 void bfs()
     49 {
     50     fl[n]=S-l[n],fr[n]=r[n]-S;
     51     queue<int> Q;
     52     Q.push(n);
     53     while (!Q.empty())
     54     {
     55         int cur=Q.front();
     56         Q.pop(),inq[cur]=false;
     57         int next1=pl[cur],next2=pr[cur];
     58         
     59         if (next1==0) ans=min(ans,fl[cur]+abs(add-l[cur]));
     60         else
     61         {
     62             if (fl[cur]+l[cur]-l[next1]<fl[next1] || fl[cur]+r[next1]-l[cur]<fr[next1])
     63             {
     64                 fl[next1]=min(fl[next1],fl[cur]+l[cur]-l[next1]);
     65                 fr[next1]=min(fr[next1],fl[cur]+r[next1]-l[cur]);
     66                 if (!inq[next1]) Q.push(next1),inq[next1]=true;
     67             }
     68         }
     69         
     70         if (next2==0) ans=min(ans,fr[cur]+abs(add-r[cur]));
     71         else
     72         {
     73             if (fr[cur]+r[cur]-l[next2]<fl[next2] || fr[cur]+r[next2]-r[cur]<fr[next2])
     74             {
     75                 fl[next2]=min(fl[next2],fr[cur]+r[cur]-l[next2]);
     76                 fr[next2]=min(fr[next2],fr[cur]+r[next2]-r[cur]);
     77                 if (!inq[next2]) Q.push(next2),inq[next2]=true;
     78             }
     79         }
     80     }
     81 }
     82 
     83 int main()
     84 {
     85     //while (scanf("%d%d",&n,&S)!=EOF)
     86     {
     87         scanf("%d%d",&n,&S);
     88         S+=add;
     90         memset(fl,0x3f,sizeof fl);
     91         memset(fr,0x3f,sizeof fr);
     92         for (int i=1; i<=n; i++)
     93         {
     94             scanf("%d%d",&l[i],&r[i]);
     95             l[i]+=add,r[i]+=add;
     96             pl[i]=query(1,1,maxn,l[i]);
     97             pr[i]=query(1,1,maxn,r[i]);
     98             update(1,1,maxn,l[i],r[i],i);
     99         }
    100         ans=~0U>>2;
    101         bfs();
    102         printf("%d
    ",ans);
    103     }
    104     return 0;
    105 }
    如有转载,请注明出处(http://www.cnblogs.com/lochan)
  • 相关阅读:
    adb获取不了设备List of devices attached
    Appium常用的API函数
    Clevo P950笔记本加装4G模块
    “CNKI 中国知网 PDF 全文下载”油猴脚本在线安装地址
    使用XTU降低CPU功耗,自动执行不失效
    Clevo P950系列拆机
    Win10的WSL很好用呀
    ubuntu下opencv使用cvNamedWindow()和cvShowImage()出错的解决方法
    2017年研究生数学建模D题(前景目标检测)相关论文与实验结果
    [翻译]怎么阅读一篇论文
  • 原文地址:https://www.cnblogs.com/lochan/p/3416847.html
Copyright © 2020-2023  润新知