HDU 3016
2013-08-09 01:17
369 查看
dp+线段树
dp[i]表示到达高度为i的板子上的最大体力值,next[i][0]、next[i][1]分别表示从i的左边、右边下落,将到达的板子高度。(通过排序将高度离散化)
那么递推式就是这样的:dp[next[i][k]]=max(dp[next[i][k]],dp[i]+plank[next[i][k]].v) (k=0,1) 从上到下推一遍,输出dp[0]。
现在问题是解决next数组的问题。ps:从板子(xl,xr) 左边下落的位置是xl而不是xl-1,同理右边是xr。
从上往下找板子的next不好找,上面板子覆盖下面板子的缘故。所以我们先找下面板子的next,每找完一个板子,就让它覆盖下面的板子。
这就等价于一个染色的问题。用线段树解决即可。
dp[i]表示到达高度为i的板子上的最大体力值,next[i][0]、next[i][1]分别表示从i的左边、右边下落,将到达的板子高度。(通过排序将高度离散化)
那么递推式就是这样的:dp[next[i][k]]=max(dp[next[i][k]],dp[i]+plank[next[i][k]].v) (k=0,1) 从上到下推一遍,输出dp[0]。
现在问题是解决next数组的问题。ps:从板子(xl,xr) 左边下落的位置是xl而不是xl-1,同理右边是xr。
从上往下找板子的next不好找,上面板子覆盖下面板子的缘故。所以我们先找下面板子的next,每找完一个板子,就让它覆盖下面的板子。
这就等价于一个染色的问题。用线段树解决即可。
#include<stdio.h> #include<iostream> #include<memory.h> #include<algorithm> using namespace std; #define Maxn 100010 struct node { int h,l,r,v; }plank[Maxn]; struct T { int l,r,c,lchild,rchild; }tree[4*Maxn]; int next[Maxn][2],cnt,dp[Maxn],n; bool cmp(node a,node b) { return a.h<b.h; } void Init(); void build(int l,int r); void revise(int k,int l,int r,int c); int inquiry(int k,int x); int main() { while(scanf("%d",&n)!=EOF) { memset(dp,-1,sizeof(dp)); for(int i=1;i<=n;i++) scanf("%d%d%d%d",&plank[i].h,&plank[i].l,&plank[i].r,&plank[i].v); sort(plank+1,plank+1+n,cmp); Init(); dp =100+plank .v; for(int i=n;i>0;i--) { if(dp[i]<=0) continue; dp[next[i][0]]=max(dp[next[i][0]],dp[i]+plank[next[i][0]].v); dp[next[i][1]]=max(dp[next[i][1]],dp[i]+plank[next[i][1]].v); } printf("%d\n",dp[0]); } return 0; } void build(int l,int r) { int i=cnt; tree[i].l=l,tree[i].r=r,tree[i].c=0; if(l==r) return; tree[i].lchild=++cnt; build(l,(r+l)/2); tree[i].rchild=++cnt; build((r+l)/2+1,r); } void revise(int k,int l,int r,int c) { if(l>r) return; int cntl,cntr,cntm; cntl=tree[k].l,cntr=tree[k].r; cntm=(cntl+cntr)/2; if(l==cntl && r==cntr) { tree[k].c=c; revise(tree[k].lchild,l,cntl-1,c); revise(tree[k].rchild,cntr+1,r,c); return; } if(tree[k].c!=-1) { tree[tree[k].lchild].c=tree[k].c; tree[tree[k].rchild].c=tree[k].c; tree[k].c=-1; } if(l<=cntm) { if(r<=cntm) revise(tree[k].lchild,l,r,c); else { revise(tree[k].lchild,l,cntm,c); revise(tree[k].rchild,cntm+1,r,c); } } else { revise(tree[k].rchild,l,r,c); } } void Init() { cnt=0; build(0,Maxn); for(int i=1;i<=n;i++) { next[i][0]=inquiry(0,plank[i].l); next[i][1]=inquiry(0,plank[i].r); revise(0,plank[i].l,plank[i].r,i); } } int inquiry(int k,int x) { if(tree[k].c!=-1) return tree[k].c; if(x<=(tree[k].l+tree[k].r)/2) return inquiry(tree[k].lchild,x); else return inquiry(tree[k].rchild,x); }
相关文章推荐
- hdu 3016 Man Down(线段树)
- hdu 3016(线段树+dp)
- 线段树专辑—— hdu 3016 Man Down
- hdu 3016 Man Down
- hdu 3016 #线段树 #线段覆盖
- hdu 3016(线段树 + DP)
- hdu-3016-Man Down(线段树)
- HDU 3016 Man Down(线段树+离散化+dp)
- HDU 3016 线段树单点更新+DP
- HDU-3016 Man Down 线段树
- HDU-3016:Man Down(线段树+DP)
- HDU 3016 Man Down 线段树+简单DP
- HDU 3016 Man Down
- HDU 3016 Man Down
- HDU 3016 Man Down(线段树)
- hdu 3016 Man Down
- HDU 3016 Man Down
- HDU 3016 线段树区间更新+spfa
- hdu 3016 Man Down(线段树)
- Man Down HDU - 3016