hdu 3016(线段树+dp)

来源:互联网 发布:淘宝一般星期几流量高 编辑:程序博客网 时间:2024/06/10 09:14

看了别人的博客才AC的。

这题以dp为主要,线段树打辅助,线段树为后面的dp做铺垫!

首先想怎么dp:

1、建立一个结构体

struct plank{

          int h , l , r, value;//木板本身的属性,高度、左端点、右端点、值

          int vl , vr;        //从木板左边跳到vl木板 , 右边跳到vr木板

          plank(int H = 0, int L = 0, int R = 0,int V = 0){

                    h = H , l = L , r = R ,value = V;

          }

};

2、把木板按照高度从低到高排序

3、状态转移方程,很好理解,看看就能懂

for(int i = N;i >=1;i--){

        dp[p[i].vl] = max(dp[p[i].vl] ,dp[i]+p[p[i].vl].value);

        dp[p[i].vr] = max(dp[p[i].vr] ,dp[i]+p[p[i].vr].value);

}

然后,想求出plank中的vl、vr,就用线段树!

1、

struct tree{

        int l , r , id;//id指l到r区间,第几块木板,初始化为0,我们木板的编号从1开始,0表示地板;

}a[4*maxn];

4

5 2 4 100 //plank4

4 1 3 100 //plank3

3 3 4 100 //plank2

2 1 4 100 //plank1






#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 100010;struct plank{int h , l , r, value;int vl , vr;plank(int H = 0, int L = 0, int R = 0, int V = 0){h = H , l = L , r = R , value = V;}}p[maxn];struct tree{int l , r , id;}a[4*maxn];int N , dp[maxn];bool cmp(plank p1 , plank p2){return p1.h < p2.h;}void pushdown(int k){if(a[k].l != a[k].r){a[2*k].id = a[k].id;a[2*k+1].id = a[k].id;a[k].id = -1;}}void build(int l , int r , int k){a[k].l = l;a[k].r = r;a[k].id = 0;if(l != r){int mid = (l+r)/2;build(l , mid , 2*k);build(mid+1 , r , 2*k+1);}}int query(int k , int x){if(a[k].id != -1){return a[k].id;}else{int mid = (a[k].l+a[k].r)/2;if(mid >= x){return query(2*k , x);}else{return query(2*k+1 , x);}}}void add(int l , int r , int k, int id){if(l <= a[k].l && a[k].r <= r){a[k].id = id;}else{if(a[k].id != -1){pushdown(k);}int mid = (a[k].l+a[k].r)/2;if(mid >= r){add(l , r , 2*k , id);}else if(mid < l){add(l , r , 2*k+1 , id);}else{add(l , mid , 2*k , id);add(mid+1 , r , 2*k+1 , id);}}}void initial(){for(int i = 0;i < maxn;i++){dp[i] = 0;p[i].value = 0;}}void readcase(){int h , xl , xr , v , M_r = 0;for(int i = 1;i <= N;i++){scanf("%d%d%d%d" , &h , &xl , &xr , &v);p[i] = plank(h , xl ,xr , v);M_r = max(M_r , xr);}build(1 , M_r , 1);}void computing(){sort(p+1 , p+N+1 , cmp);for(int i = 1;i <= N;i++){p[i].vl = query(1 , p[i].l);p[i].vr = query(1 , p[i].r);add(p[i].l , p[i].r , 1 , i);//cout << i << ":" << p[i].vl << " " << p[i].vr << endl;}dp[N] = p[N].value+100;for(int i = N;i >= 1;i--){dp[p[i].vl] = max(dp[p[i].vl] , dp[i]+p[p[i].vl].value);dp[p[i].vr] = max(dp[p[i].vr] , dp[i]+p[p[i].vr].value);//cout << dp[i] << ":" << p[i].vl <<"=" << dp[p[i].vl] << " " <<p[i].vr <<"=" << dp[p[i].vr]<<endl;}if(dp[0]>0){cout << dp[0] << endl;}else{cout << -1 << endl;}}int main(){while(cin >> N){initial();readcase();computing();}return 0;}


原创粉丝点击