4 10 5 10 10 5 3 6 -100 4 7 11 20 2 2 1000 10
140
题意:
题目是以"是男人就下一百层"游戏为背景。不过加以简化了。就说只有两种木板了。一种到达上面后可以得到上面的分数。另一种就减相应的分数。每一个木板会给你它的左右端点的坐标。[xl,xr]。然后小人会到达高度比当前木板低。
且满足。xl'<=xl<=xr'或。xl'<=xr<=xr'。的最近木板上。因为它只能从当前木板的左边或右边下去嘛。
如果不存在这样的木板。他就完成了它的使命。(因为玩过这个游戏的缘故我开始以为他挂掉了然后wa了数次)
还有如果中途分数小于或等于0的话那么它就挂掉了。初始分为100.
思路:
由于这是在线段树专题里找的题。于是拼命往线段树上想。白白YY那么久。其实这题就是一简单DP因为对于一个木板要么从左边下去。要么从右边下去。但由于高度不连续所以处理有点不同。这题关键在处理最近上。我们可以用一颗线段树来维护。先把木板高度按高度升序排序。然后对于当前木板。查一下它左右端点被谁覆盖了用数组记录下来。因为是升序排序的。查到的一定是最近的。然后再用这木板去覆盖点。循环做。我开始想着从终点倒着走回去
就不用记录了。但发现有bug。因为有可能存在正这走挂了。倒着走不挂的情况。
4
5 2 6 100
4 1 4 -200
3 5 8 -200
2 1 10 500
所以只能走。
详细见代码:
#include<algorithm> #include<iostream> #include<string.h> #include<sstream> #include<stdio.h> #include<math.h> #include<vector> #include<string> #include<queue> #include<set> #include<map> using namespace std; const int INF=0x3f3f3f3f; const int maxn=100010; int dp[maxn],id[maxn<<2],li[maxn],ri[maxn]; struct node { int h,xl,xr,val; } plan[maxn]; bool cmp(node a,node b) { return a.h<b.h; } void btree(int L,int R,int k) { int ls,rs,mid; id[k]=0; if(L==R) return ; ls=k<<1; rs=ls|1; mid=(L+R)>>1; btree(L,mid,ls); btree(mid+1,R,rs); } void pushdown(int k) { int ls,rs; ls=k<<1; rs=ls|1; id[ls]=id[rs]=id[k]; id[k]=0; } void update(int L,int R,int l,int r,int k,int d) { int ls,rs,mid; if(l==L&&r==R) { id[k]=d; return; } if(id[k]) pushdown(k); ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(l>mid) update(mid+1,R,l,r,rs,d); else if(r<=mid) update(L,mid,l,r,ls,d); else { update(L,mid,l,mid,ls,d); update(mid+1,R,mid+1,r,rs,d); } } int qu(int L,int R,int p,int k) { int ls,rs,mid; if(L==R||id[k]) return id[k]; ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(p>mid) return qu(mid+1,R,p,rs); else return qu(L,mid,p,ls); } int main() { int n,i,lim; while(~scanf("%d",&n)) { lim=0; plan[0].val=0; dp[0]=-INF; for(i=1;i<=n;i++) { scanf("%d%d%d%d",&plan[i].h,&plan[i].xl,&plan[i].xr,&plan[i].val); lim=max(lim,plan[i].xr); dp[i]=-INF; } sort(plan+1,plan+n+1,cmp); btree(1,lim,1); for(i=1;i<=n;i++) { li[i]=qu(1,lim,plan[i].xl,1); ri[i]=qu(1,lim,plan[i].xr,1); update(1,lim,plan[i].xl,plan[i].xr,1,i); } dp[n]=100+plan[n].val; for(i=n;i>=1;i--) { if(dp[i]>0)//题目数据有点水。不加这个判断也能过。 { dp[li[i]]=max(dp[li[i]],dp[i]+plan[li[i]].val); dp[ri[i]]=max(dp[ri[i]],dp[i]+plan[ri[i]].val); } } if(dp[0]<=0) dp[0]=-1; printf("%d\n",dp[0]); } return 0; } /* 4 5 2 6 100 4 1 4 -200 3 5 8 -200 2 1 10 500 2 5 2 6 100 4 1 4 -200 */ /* -1//数据水了。不是-1也行。 100 */