这个题意类似是男人就下100层的游戏的简化版,给你一些包含权值的木板,每次只能从左边和右边进行下落,开始处于最高处,求下落到地上的时候最大权值是多少。
只需要用线段树求出每个木板最左边和最右边下面最近的板子,然后求一遍最长路径就行了。
需要注意的是:
1、地板需要自己添加一个"木板"
2、最开始所在的木板要算权值,并且开始的时候权值为100,则实际开始的权值为100+开始所在的木板
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1<<29;
const int maxn=1e5+100;
const int maxm=maxn*4;
const int maxr=1e5;
struct Blank
{
int sl;
int sr;
int h;
int v;
Blank(){}
Blank(int ssl,int ssr,int sh,int sv)
{
sl=ssl;
sr=ssr;
h=sh;
v=sv;
}
bool operator < (const Blank &a)const{
return h<a.h;
}
}a[maxn];
struct Node
{
int l;
int r;
int maxh;
int isall;
}t[maxm];
int n,e,head[maxn],nxt[maxm],pnt[maxm],cost[maxm],dist[maxn];
bool vis[maxn];
queue<int> q;
void Build(int l,int r,int index)
{
t[index].l=l;
t[index].r=r;
t[index].maxh=t[index].isall=0;
if(l==r)
return;
int mid=(l+r)>>1;
Build(l,mid,index<<1);
Build(mid+1,r,index<<1|1);
}
void PushDown(int index)
{
if(t[index].l==t[index].r)
return;
t[index<<1].maxh=t[index<<1|1].maxh=t[index].maxh;
t[index<<1].isall=t[index<<1|1].isall=1;
t[index].isall=false;
}
void Update(int l,int r,int index,int val)
{
if(t[index].l==l&&t[index].r==r)
{
t[index].isall=1;
t[index].maxh=val;
return;
}
if(t[index].isall)
PushDown(index);
int mid=(t[index].l+t[index].r)>>1;
if(r<=mid)
Update(l,r,index<<1,val);
else if(l>mid)
Update(l,r,index<<1|1,val);
else
{
Update(l,mid,index<<1,val);
Update(mid+1,r,index<<1|1,val);
}
}
int Query(int l,int index)
{
if(t[index].isall||t[index].l==t[index].r)
return t[index].maxh;
if(t[index].isall)
PushDown(index);
int mid=(t[index].l+t[index].r)>>1;
if(l<=mid)
return Query(l,index<<1);
return Query(l,index<<1|1);
}
void AddEdge(int u,int v,int c)
{
pnt[e]=v;nxt[e]=head[u];cost[e]=c;head[u]=e++;
}
void Spfa(int st,int des)
{
for(int i=0;i<=n;i++)
dist[i]=-inf;
dist[st]=100+a[n-1].v;
q.push(st);
while(!q.empty())
{
int u=q.front();
vis[u]=0;
q.pop();
for(int i=head[u];i!=-1;i=nxt[i])
if(dist[pnt[i]]<dist[u]+cost[i])
{
dist[pnt[i]]=dist[u]+cost[i];
if(!vis[pnt[i]])
{
vis[pnt[i]]=1;
q.push(pnt[i]);
}
}
}
if(dist[des]<0)
printf("-1\n");
else
printf("%d\n",dist[des]);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
e=0;
memset(head,-1,sizeof(head));
for(int i=0;i<n;i++)
scanf("%d%d%d%d",&a[i].h,&a[i].sl,&a[i].sr,&a[i].v);
a[n++]=Blank(0,maxr,0,0);
sort(a,a+n);
Build(0,maxr,1);
Update(a[0].sl,a[0].sr,1,0);
for(int i=1;i<n;i++)
{
int x=Query(a[i].sl,1);
int y=Query(a[i].sr,1);
Update(a[i].sl,a[i].sr,1,i);
AddEdge(i,x,a[x].v);
AddEdge(i,y,a[y].v);
}
Spfa(n-1,0);
}
return 0;
}