hdu 3016 man down
先用简单线段树记录当前线段的左右两端下来的线段编号
再从上往下dp下来即可
具体做法:先按高度升序排序,依次插入各条线段,每次先询问,后插入
线段树只有一个域id【x】,表示当前区域被哪个线段完全覆盖
View Code
#include<cstdio>
#include<cstring>
#include<ctype.h>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 111111;
int id[maxn<<2];
struct seg{
int l,r,h,val;
bool operator < (const seg &cmp)const{
return h<cmp.h;
}
}ss[maxn];
struct pp{
int l,r;
}path[maxn];
void pushdown(int rt){
if(id[rt]!=-1){
id[rt<<1]=id[rt<<1|1]=id[rt];
id[rt]=-1;
}
}
void update(int p,int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
id[rt]=p;
return ;
}
pushdown(rt);
int m=(l+r)>>1;
if(L<=m) update(p,L,R,lson);
if(R>m) update(p,L,R,rson);
}
int query(int p,int l,int r,int rt){
if(id[rt]!=-1&&l<=p&&p<=r) return id[rt];
int m=(l+r)>>1;
if(p<=m) return query(p,lson);
else return query(p,rson);
}
int dp[maxn];
int main(){
int n,i,j;
while(scanf("%d",&n)!=EOF){
int len=0;
memset(id,0,sizeof(id));
for(i=1;i<=n;i++){
scanf("%d%d%d%d",&ss[i].h,&ss[i].l,&ss[i].r,&ss[i].val);
if(ss[i].r>len) len=ss[i].r;
}
sort(ss+1,ss+n+1);
for(i=1;i<=n;i++){
path[i].l=query(ss[i].l,1,len,1);
path[i].r=query(ss[i].r,1,len,1);
update(i,ss[i].l,ss[i].r,1,len,1);
}
memset(dp,0,sizeof(dp));
dp[n]=100+ss[n].val;
for(i=n;i>=0;i--){
if(dp[i]){
dp[path[i].l]=max(dp[path[i].l],dp[i]+ss[path[i].l].val);
dp[path[i].r]=max(dp[path[i].r],dp[i]+ss[path[i].r].val);
}
}
printf("%d\n",dp[0] ? dp[0] : -1);
}
return 0;
}