[Luogu P1442 iron ball landing] problem solution

Iron ball landing

Title Description

One over N (n≤100000) platform has an iron ball after every fall on a platform, the player can choose to roll left or right, the ball rolling and falling speed is 1. Since the quality of the iron ball is not very good, each time falling height can not exceed MAX. Design a strategy so that the ball fell to the ground as quickly as possible without being smashed. Ground level is assumed as 0, and infinitely wide.

Input Format

The first line is two numbers n, max.

The second line of two numbers, respectively horizontal and vertical coordinates of the starting position of the iron ball.

Next row n, the i-th row is a positive integer of three hi, li, ri,

Input data to ensure a solution, and the different heights of the platform, each edge value and the abscissa are different from each other.

Output Format

Only a number, for the shortest time to reach the iron ball the ground.

Sample input and output

Input # 1
5 3
6 10
5 2 4
9 3 9
6 7 10
2 1 5
3811 

This problem should be easy to think of using dp solved.
We sorted according to the height of each board first.
Then we traverse the boards in reverse order from low to high order.
You may ask why the order from low to high dp.
In fact, from high to low in order to dp, in fact, not from high to low is not.
But from low to high it will be more convenient.
Because from low to high, we need only consider the plank from the left to reach the whereabouts and the whereabouts of two planks arriving from the right to inherit it.
However, from high to low, we do not easily find the whereabouts of which can reach the wood.
These are nonsense

if we have obtained what about the whereabouts of wood planks will arrive,
we remember ch [i] [1/0] 0 represents the left side of the whereabouts of wood to reach i, 1 represents the board to the right of the whereabouts of arrival.
    dp [i] [1/0] 0 indicates if the fall board to the left, the minimum time-consuming, falling to the right of plank 1 represents the minimum time-consuming.
    La [i] denotes the i point right abscissa, ra [i] i represents the left point abscissa.
    a [i] .h i wood recorded height.
dp equation is as follows: 

  dp[i][0]=min(dp[i][0],dp[ch[i][0]][0]+la[i]-la[ch[i][0]]+a[i].h-a[ch[i][0]].h);
  dp[i][0]=min(dp[i][0],dp[ch[i][0]][1]+ra[ch[i][0]]-la[i]+a[i].h-a[ch[i][0]].h);

  dp[i][1]=min(dp[i][1],dp[ch[i][1]][0]+ra[i]-la[ch[i][1]]+a[i].h-a[ch[i][1]].h);
  dp[i][1]=min(dp[i][1],dp[ch[i][1]][1]+ra[ch[i][1]]-ra[i]+a[i].h-a[ch[i][1]].h);

In fact, behind this shift is to simulate the path is not difficult to understand.

 

dp equation is solved, there is a problem, and that is how to deal with each of the planks of wood behind at about arriving?

A better understanding of the program is to segment tree.

 

This uses the interval assignment and a single point of modification .

We enumerate wood from low to high, the query value left / right end of the line corresponding to the tree.

This value is the fall in the number of our wood requirements.

When the board finished, he is the corresponding interval (wood left point to the right end point), the top of the board.

Above it should fall on top of it.

So interval changes. The value of this range of modifications for the board number.

This, the problem is the perfect solution

 

And so, we must not forget discrete, and especially when sentenced dp.

If the current whereabouts of the wooden planks are numbered 0, then dp is the height of the current board.

 

Specific look at the code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls k<<1
#define rs k<<1|1
typedef long long ll;
using namespace std;
const int N=1e6;
ll n,m,cnt;
ll lx[N<<2],ch[N][2],w[N<<4],tag[N<<4];//
ll la[N<<2],ra[N<<2],dp[N][2];//
struct node{
    ll l,r,h,id;//需要记录一个编号,因为需要排序
    bool operator < (const node &b) const {
        return h<b.h;//按高度从矮到高排序
    }
}a[N];
inline void read(ll &x){
    x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
}
inline void update(ll k,ll x,ll y){
    tag[ls]=tag[k];
    w[ls]=tag[k];
    tag[rs]=tag[k];
    w[rs]=tag[k];
    tag[k]=0;
}
inline void change(ll k,ll x,ll y,ll l,ll r,ll val){
    if(x>r||y<l) return;
    if(x>=l&&y<=r){//区间赋值
        tag[k]=val;
        w[k]=val;
        return;
    }
    ll mid=x+y>>1;
    if(tag[k]) update(k,x,y);//区间赋值的标记下传
    change(ls,x,mid,l,r,val);
    change(rs,mid+1,y,l,r,val);
}
inline ll query(ll k,ll x,ll y,ll pos){
    if(x>pos||y<pos) return 0;
    if(x==y) return w[k];//单点查询,w记录当前区间对应最上方的木板编号
    ll mid=x+y>>1;
    if(tag[k]) update(k,x,y);
    return query(ls,x,mid,pos)+query(rs,mid+1,y,pos);
}
int main()
{
    ll i,j,stx,sty;
    read(n),read(m);
    read(stx),read(sty);
    n++;//有一个起始位置
    a[n].l=a[n].r=stx;
    a[n].h=sty,a[n].id=n;
    la[n]=stx,ra[n]=stx;
    lx[++cnt]=a[n].l;
    for(i=1;i<n;i++){
        read(a[i].h),read(a[i].l),read(a[i].r);
        a[i].id=i;
        la[i]=a[i].l;
        ra[i]=a[i].r;//la[] ra[]记录原来i木板的左右端点位置,因为需要离散化。
        lx[++cnt]=a[i].l;//lx[] 为离散化数组
        lx[++cnt]=a[i].r;
    }
    sort(lx+1,lx+cnt+1);//离散化数组排序
    sort(a+1,a+1+n);//木板高度排序
    for(i=1;i<=n;i++){//区间离散化
        a[i].l=lower_bound(lx+1,lx+1+cnt,a[i].l)-lx;
        a[i].r=lower_bound(lx+1,lx+1+cnt,a[i].r)-lx;
    }
    for(i=1;i<=n;i++){//点查询,不再多说
        ch[i][0]=query(1,1,cnt,a[i].l);
        ch[i][1]=query(1,1,cnt,a[i].r);
        change(1,1,cnt,a[i].l,a[i].r,i);
    }
    memset(dp,0x3f,sizeof(dp));
    dp[0][0]=dp[0][1]=0;//显而易见的初始化
    for(i=1;i<=n;i++){
        if(a[i].h-a[ch[i][0]].h<=m){//如果大于m不能转移
            if(ch[i][0]){//编号为0这带到到达地面
                 dp[i][0]=min(dp[i][0],dp[ch[i][0]][0]+la[a[i].id]-la[a[ch[i][0]].id]+a[i].h-a[ch[i][0]].h);
                 dp[i][0]=min(dp[i][0],dp[ch[i][0]][1]+ra[a[ch[i][0]].id]-la[a[i].id]+a[i].h-a[ch[i][0]].h);//加了离散数组的方程,一点点小变化
             }
             else dp[i][0]=a[i].h;
        }
        if(a[i].h-a[ch[i][1]].h<=m){
            if(ch[i][1]){
                dp[i][1]=min(dp[i][1],dp[ch[i][1]][0]+ra[a[i].id]-la[a[ch[i][1]].id]+a[i].h-a[ch[i][1]].h);
                dp[i][1]=min(dp[i][1],dp[ch[i][1]][1]+ra[a[ch[i][1]].id]-ra[a[i].id]+a[i].h-a[ch[i][1]].h);
            }
            else dp[i][1]=a[i].h;
        }
    }
    printf("%d",min(dp[n][0],dp[n][1]));//最后答案为转移到起始位置 n 的值。
}//刚好99行

 

Guess you like

Origin www.cnblogs.com/quitter/p/11739315.html