Man Down(线段树dp)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Man Down(线段树dp)相关的知识,希望对你有一定的参考价值。

Man Down(线段树dp)

是男人就下100层的模拟,因为每个平台往左和往右的状态是确定的,这可以通过线段树的区间覆盖,单点查询求,然后就是从高往低dp。

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

区间覆盖不需要 l a z t   t a g lazt \\ tag lazt tag,换句话说 a [ x ] . c o l o r a[x].color a[x].color 就是 l a z y   t a g lazy \\ tag lazy tag

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
//区间修改 区间求和
#define il inline 
#define lx x<<1
#define rx x<<1|1
#define len(x) (a[x].r-a[x].l+1)
struct node{
	int l,r;
	int s;
}a[N<<2];
il void re(int x){
	if(a[lx].s==a[rx].s) a[x].s=a[lx].s;
	else a[x].s=0;
}
il void ptg(int x,int y){
	a[x].s=y;
}
il void pd(int x){
	if(a[x].s){
		ptg(lx,a[x].s),ptg(rx,a[x].s);
		a[x].s=0;
	}
}
il void bud(int x,int l,int r){
	a[x].l=l,a[x].r=r,a[x].s=0;
	if(l==r){
		return;
	}
	int m=(l+r)>>1;bud(lx,l,m),bud(rx,m+1,r);
}
il void upd(int x,int l,int r,int val){
	if(a[x].l>=l&&a[x].r<=r){
		ptg(x,val);return;
	}
	pd(x);
	int m=(a[x].l+a[x].r)>>1;
	if(l<=m) upd(lx,l,r,val);
	if(r>m) upd(rx,l,r,val);
	re(x);
}
il int que(int x,int p){
	if(a[x].l==a[x].r) return a[x].s;
	pd(x);
	int m=(a[x].l+a[x].r)>>1;
	if(p<=m) return que(lx,p);
	else return que(rx,p);
}

struct line{
	int h,xl,xr,v;
	int l,r;
	bool operator<(const line &a)const{
		return h<a.h;
	}
}b[N];
int dp[N];
int main(){
	int n;
	while(~scanf("%d",&n)){
		int rmx=0;
		mst(dp,0);
		for(int i=1;i<=n;i++){
			scanf("%d%d%d%d",&b[i].h,&b[i].xl,&b[i].xr,&b[i].v);
			if(rmx<b[i].xr) rmx=b[i].xr;
		}
		sort(b+1,b+n+1);
		bud(1,1,rmx);
		for(int i=1;i<=n;i++){
			b[i].l=que(1,b[i].xl);
			b[i].r=que(1,b[i].xr);
			upd(1,b[i].xl,b[i].xr,i);
		}
		dp[n]=100+b[n].v;
		for(int i=n;i;i--){
			if(dp[i]>0){
				dp[b[i].l]=max(dp[b[i].l],dp[i]+b[b[i].l].v);
				dp[b[i].r]=max(dp[b[i].r],dp[i]+b[b[i].r].v);
			}
		}
		if(dp[0]<=0) dp[0]=-1;
		printf("%d\\n",dp[0]);
	}
	return 0;
}

以上是关于Man Down(线段树dp)的主要内容,如果未能解决你的问题,请参考以下文章

HDU3016 Man Down 题解

HDU 4521 小明系列问题——小明序列 (线段树维护DP)

群赛 ZOJ3741(dp) ZOJ3911(线段树)

线段树+dppoj3171

AtCoder abc256全题解(区间合并模板矩阵快速幂优化dp线段树……)

AtCoder abc256全题解(区间合并模板矩阵快速幂优化dp线段树……)