POJ 2374 Fence Obstacle Course 线段树+动态规划

POJ 2374 Fence Obstacle Course 线段树+动态规划

思路:

用线段树维护所有线段的分布。
新增加一个fence的时候,将fence的范围[a, b]插入线段树,节点的值为fence的编号,即高度。
那么fence上的某一点就是树的叶子了,从叶子往上一直到根节点的路径中节点的最大值,
就是从fence上的这一点垂直掉下去后,碰到的一个fence了。

这样,我们就可以在O(lgN)时间内知道,从一个fence的端点掉下去会碰到哪个fence了。
不然从后往前一个个找就是O(N)复杂度了。同时N也很大,必然超时。

同时也可以发现,一个fence保存两个值用作动态规划就好了,向左、右走之后,掉到其他fence上面,然后回到基地所用的最短路径。
推的方法很简单,掉到其他fence上面之后,看下是向左走距离短还是向右走距离短。就行了。

这个代码跑到400ms。

#include  < stdio.h >

#define  MAX_N 50032
#define  MAX_R 100032 

struct   {
    
int a, b;
}
 dp[MAX_N], fences[MAX_N];
int  N, S, tree[MAX_R * 16 ];

__inline 
int  max( int  a,  int  b)
{
    
return a > b ? a : b;
}


__inline 
int  abs( int  a)
{
    
return a > 0 ? a : -a;
}


__inline 
int  min( int  a,  int  b)
{
    
return a < b ? a : b;
}


void  insert( int  idx,  int  start,  int  end,  int  left,  int  right,  int  val)
{
    
int mid;

    
if (start == left && right == end) {
        tree[idx] 
= val;
        
return ;
    }

    mid 
= (start + end) / 2;
    
if (right <= mid) 
        insert(idx
*2, start, mid, left, right, val);
    
else if (left > mid)
        insert(idx
*2+1, mid + 1, end, left, right, val);
    
else {
        insert(idx
*2, start, mid, left, mid, val);
        insert(idx
*2+1, mid + 1, end, mid + 1, right, val);
    }

}


int  query( int  idx,  int  start,  int  end,  int  pos)
{
    
int val, mid;

    
if (start == pos && end == pos) 
        
return tree[idx];
    mid 
= (start + end) / 2;
    
if (pos <= mid)
        val 
= query(idx*2, start, mid, pos);
    
else
        val 
= query(idx*2+1, mid + 1, end, pos);
    
return max(val, tree[idx]);
}


__inline 
int  calc_min( int  i,  int  pos)
{
    
if (!i)
        
return abs(pos - MAX_R);
    
return min(pos - fences[i].a + dp[i].a, fences[i].b - pos + dp[i].b);
}


int  main()
{
    
int i;

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d"&N, &S);
    S 
+= MAX_R;
    
for (i = 1; i <= N; i++{
        scanf(
"%d%d"&fences[i].a, &fences[i].b);
        fences[i].a 
+= MAX_R;
        fences[i].b 
+= MAX_R;
        dp[i].a 
= calc_min(query(10, MAX_R*2, fences[i].a), fences[i].a);
        dp[i].b 
= calc_min(query(10, MAX_R*2, fences[i].b), fences[i].b);
        insert(
10, MAX_R*2, fences[i].a, fences[i].b, i);
    }

    printf(    
"%d\n"
            min(S 
- fences[N].a + dp[N].a, fences[N].b - S + dp[N].b)
            );

    
return 0;
}

你可能感兴趣的:(POJ 2374 Fence Obstacle Course 线段树+动态规划)