https://vjudge.net/problem/POJ-2374


吐槽。在这题上面磕了许久。。英文不好题面读错了qwq,写了个错的算法搞了很久。。A掉之后瞥了一眼众多julao题解,**,怎么想的方法都比我简单,码量还小?太菜了太菜了,把自己烂方法记下来滚了。


题意内容说简单点其实就跟小时候玩的森林冰火人差不多。。看成一个小人从最顶层平台上开始,走到边缘会掉下去,直到落在一个平台或者底部,再继续左或右走。给n层的每层平台起讫点坐标,求x轴方向最小移动距离。

先想到设计状态$f[i][0/1]$表示在第$i$层时($i$从上往下递增),走到最左端或最右端时横向最小移动步数。然后倒序枚举之前每一层,如果可以从其边缘落到现在这层的话,转移之,并且每个线段处理之后覆盖起来,以判断上一层端点是否在覆盖区域内以判断能否掉到这层来。然后发现这个思路优化不了。。$O(n^2logn)$。

换一下思路,看可不可以按dp顺序自顶向下按顺序每dp完一个,就顺带覆盖一次线段。之前可行的端点,可能被覆盖之后就不可行了。所以每次dp完在把当前线段所涵盖的合法端点全清掉,把现在两个端点加入,对于所dp区间内每个横坐标看一下其作为平台端点最晚出现在哪一层,这就是合法决策。

再看转移优化,若合法决策层是$j$,则

$f[i][0]=min \{ min(f[j][0]+l[j]-l[i],f[j][1]+r[j]-l[i])\}$

$f[i][1]=min \{min(f[j][0]+r[i]-l[j],f[j][1]+r[i]-r[j])\}$。(因为abs很讨厌,所以拆开)

发现其实际只与$j$有关,也就是在线段区间内合法决策中(不合法设为INF)找和$j$相关的最小值,分左右端点讨论转移即可。

也就是用线段树在所在区间上的合法决策去维护这几个域:

$f[i][1]-r[i]$    (再$+r[I]$之后即是从$i$层右端下落后走到第$I$层右端的总距离,下面类推)

$f[i][1]+r[i]$  ($-l[I]$)

$f[i][0]-l[i]$  ($+r[I]$)

$f[i][0]+l[i]$  ($-l[I]$)

进一步发现可以简化成两个域(分类:走到左右)。然后分别将其min取出,和$i$有关的项拼一下完成转移。

然后每次dp完一个线段把他本身两个端点的上述信息加入线段树维护,加入前记得把这段区间所有有效端点去掉,也就是区间改成INF。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<queue>
  7. #define lc i<<1
  8. #define rc i<<1|1
  9. #define dbg(x) cerr<<#x<<" = "<<x<<endl
  10. #define _dbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl
  11. using namespace std;
  12. typedef long long ll;
  13. template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
  14. template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
  15. template<typename T>inline T _min(T A,T B){return A<B?A:B;}
  16. template<typename T>inline T _max(T A,T B){return A>B?A:B;}
  17. template<typename T>inline T read(T&x){
  18. x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
  19. while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
  20. }
  21. const int N=+,M=+,INF=0x3f3f3f3f;
  22. int a[N][],f[N][];
  23. int minv0[M<<],minv1[M<<],tag[M<<];
  24. int n,s,Lbound,Rbound,ql,qr;
  25.  
  26. inline void pushdown(int i){if(tag[i])minv0[lc]=minv0[rc]=minv1[lc]=minv1[rc]=INF,tag[lc]=tag[rc]=,tag[i]=;}
  27. void Delete(int i,int L,int R){
  28. if(ql<=L&&qr>=R){tag[i]=,minv0[i]=minv1[i]=INF;return;}
  29. if(tag[i])return;int mid=L+R>>;
  30. if(ql<=mid)Delete(lc,L,mid);if(qr>mid)Delete(rc,mid+,R);
  31. minv0[i]=_min(minv0[lc],minv0[rc]),minv1[i]=_min(minv1[lc],minv1[rc]);
  32. }
  33. void Update(int i,int L,int R,int k,int p){
  34. if(L==R){MIN(minv0[i],f[k][p]+a[k][p]),MIN(minv1[i],f[k][p]-a[k][p]);return;}
  35. pushdown(i);int mid=L+R>>;
  36. a[k][p]<=mid?Update(lc,L,mid,k,p):Update(rc,mid+,R,k,p);
  37. minv0[i]=_min(minv0[lc],minv0[rc]),minv1[i]=_min(minv1[lc],minv1[rc]);
  38. }
  39. int Query_min0(int i,int L,int R){
  40. if(ql<=L&&qr>=R)return minv0[i];
  41. if(tag[i])return INF;int mid=L+R>>,ret=INF;
  42. if(ql<=mid)MIN(ret,Query_min0(lc,L,mid));
  43. if(qr>mid)MIN(ret,Query_min0(rc,mid+,R));
  44. return ret;
  45. }
  46. int Query_min1(int i,int L,int R){
  47. if(ql<=L&&qr>=R)return minv1[i];
  48. if(tag[i])return INF;int mid=L+R>>,ret=INF;
  49. if(ql<=mid)MIN(ret,Query_min1(lc,L,mid));
  50. if(qr>mid)MIN(ret,Query_min1(rc,mid+,R));
  51. return ret;
  52. }
  53. #define all 1,Lbound,Rbound
  54. int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
  55. read(n),a[][]=read(a[][]);Lbound=Rbound=a[][];MIN(Lbound,),MAX(Rbound,);
  56. for(register int i=;i<=n;++i)MIN(Lbound,read(a[n-i+][])),MAX(Rbound,read(a[n-i+][]));
  57. memset(minv0,0x3f,sizeof minv0),memset(minv1,0x3f,sizeof minv1);
  58. Update(all,,),Update(all,,);
  59. for(register int i=;i<=n;++i){
  60. f[i][]=f[i][]=INF;ql=a[i][],qr=a[i][];
  61. MIN(f[i][],Query_min0(all)-ql);
  62. MIN(f[i][],Query_min1(all)+qr);
  63. Delete(all),Update(all,i,),Update(all,i,);
  64. }
  65. int ans=INF;
  66. ql=Lbound,qr=;MIN(ans,Query_min1(all));
  67. ql=,qr=Rbound;MIN(ans,Query_min0(all));
  68. printf("%d\n",ans);
  69. return ;
  70. }

poj2374 Fence Obstacle Course[线段树+DP]的更多相关文章

  1. POJ 2374 Fence Obstacle Course(线段树+动态规划)

    Fence Obstacle Course Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 2524   Accepted:  ...

  2. Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    [题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...

  3. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  4. POJ2374 Fence Obstacle Course 【线段树】

    题目链接 POJ2374 题解 题意: 给出\(n\)个平行于\(x\)轴的栅栏,求从一侧栅栏的某个位置出发,绕过所有栅栏到达另一侧\(x = 0\)位置的最短水平距离 往上说都是线段树优化dp 我写 ...

  5. POJ2374 Fence Obstacle Course

    题意 Language:Default Fence Obstacle Course Time Limit: 3000MS Memory Limit: 65536K Total Submissions: ...

  6. 【bzoj3387-跨栏训练】线段树+dp

    我们可以想到一个dp方程:f[i][0]表示当前在i个栅栏的左端点,f[i][1]表示在右端点. 分两种情况: 第一种:假设现在要更新线段gh的左端点g,而它下来的路径被ef挡住了,那么必定是有ef来 ...

  7. lightoj1085 线段树+dp

    //Accepted 7552 KB 844 ms //dp[i]=sum(dp[j])+1 j<i && a[j]<a[i] //可以用线段树求所用小于a[i]的dp[j ...

  8. [CF 474E] Pillars (线段树+dp)

    题目链接:http://codeforces.com/contest/474/problem/F 意思是给你两个数n和d,下面给你n座山的高度. 一个人任意选择一座山作为起始点,向右跳,但是只能跳到高 ...

  9. HDU-3872 Dragon Ball 线段树+DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3872 题意:有n个龙珠按顺序放在一列,每个龙珠有一个type和一个权值,要求你把这n个龙珠分成k个段, ...

随机推荐

  1. Oracle索引(1)概述与创建索引

    索引是为了提高数据检索效率而创建的一种独立于表的存储结构,由Oracle系统自动进行维护. 索引的概述        索引是一种可选的与表或簇相关的数据库对象,能够为数据的查询提供快捷的存储路径,减少 ...

  2. OpenGL学习进程(4)第二课:绘制图形

    本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形:     (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) ...

  3. valn 配置

    内核修改: /device drivers/Network device support/MAC-VLAN support 1.创建目录和文件#cd /usr#mkdir vlan#cd vlan#c ...

  4. FreeRtos堆栈检测应用

    Free rtos每个任务都有自己的栈空间,每个任务需要的栈大小也是不同的.如果堆栈过小就会造成栈溢出,有时候栈溢出发生在某种特定顺序的任务切换中,比较难检测出.所以前期测试和监控任务栈用量就显得尤其 ...

  5. yield 表达式形式的应用

    import random foods=['banana','apple','peach','grape','pear'] def deco(func): def wrapper(*args,**kw ...

  6. Cocos2d-x项目移植到WP8系列之三:C++和C#的交互

    原文链接: http://www.cnblogs.com/zouzf/p/3971021.html 上一篇提到工程使用 XAML 和 Direct3D 项目模板 是因为要涉及到C++和C#的交互,微软 ...

  7. Kubernetes Kubeadm部署集群

    Kubernetes高可用架构 Kubenetes 2个高可用核心 apiserver.etcd etcd:集群数据中心,需要保持高可用,用于存放集群的配置信息.状态信息及Pod等信息.如果数据丢失集 ...

  8. Bootstrap3组件--1

     目录 1. Glyphicons字体图标 2.下拉菜单 3.按钮组 4. 输入框组 5.导航 6. 导航条 7. 路径导航 1. Glyphicons字体图标 出于性能的考虑,所有图标都需要一个基类 ...

  9. spring security在spring mvc的action中获取登录人信息

    @RequestMapping("/index") public ModelAndView login( @RequestParam(value = "error&quo ...

  10. HBase学习2(HBase shell)

    HBase 常用命令 查看当前用户:whoami 创建表:create '表名', '列族名1','列族名2','列族名N' 查看所有表:list 描述表: describe '表名' 判断表存在: ...