题目:
传送门
思路:
就题目本身而言,不是很难,可以用 o(n2) 方法解决这道题目
我们讨论的是如果这道题数据范围变成 1e4甚至1e5了怎么解决这道题目.
首先, o(n2) 解法中对于每个平台往下走转移到的下一个平台一定是确定的,而我们是用暴力的方法直接遍历所有平台.所以总复杂度为o(n2).
那既然对于某一平台,它从左端点跳下去,和从右端点跳下去的平台是固定的,我们考虑能不能先预处理出所有的可能.
显然线段树可以做到这一点,我们将平台按高度从小到大排序,线段树的叶子节点存的是 x点出现的最晚的平台编号,那我们遍历所有平台,实时查询和更新,这样我们可以在 nlog n的复杂度下预处理出所有的可能。
然后我们可以通过 o(n) 复杂度得到结果.
AC_Code
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 1e9+7;
const int maxn = 1e3+7;
struct PT
{
int x1,x2;
int h;
}s[maxn];
bool cmp(const PT& a,const PT& b) {
return a.h<b.h;
}
int n,len;
int v[maxn<<2];
int tr[maxn<<4];
int lazy[maxn<<4];
int dp[maxn][5];
int nex[maxn][5];
void pushdown(int num) {
if(lazy[num] == 0) return ;
lazy[num<<1] = lazy[num<<1|1] = lazy[num];
tr[num<<1] = lazy[num];
tr[num<<1|1] = lazy[num];
lazy[num] = 0;
return ;
}
void build(int l,int r,int num) {
lazy[num] =0;
if(l==r) {
tr[num] = 0;
return ;
}
int mid = (l+r) >>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
return ;
}
void modify(int l,int r,int num,int le,int ri,int tmp) {
if(ri<l && r<le) return ;
if(le<=l && r<= ri) {
lazy[num] = tmp;
tr[num] = tmp;
return ;
}
int mid=(l+r) >>1;
pushdown(num);
if(le<=mid) modify(l,mid,num<<1,le,ri,tmp);
if(mid< ri) modify(mid+1,r,num<<1|1,le,ri,tmp);
}
int quriy(int l,int r,int num,int pos) {
if(pos<l || r<pos) return 0;
if(l== r) return tr[num];
int mid = (l+r) >>1;
pushdown(num);
if(pos<=mid) return quriy(l,mid,num<<1,pos);
else return quriy(mid+1,r,num<<1|1,pos);
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
int now =0;
int x,y,Max;
scanf("%d%d%d%d",&n,&x,&y,&Max);
v[now++]=x;
for(int i=1;i<=n;i++) {
scanf("%d%d%d",&s[i].x1,&s[i].x2,&s[i].h);
dp[i][0] = dp[i][1] = inf;
v[now++] = s[i].x1;
v[now++] = s[i].x2;
}
dp[n+1][0] = dp[n+1][1] = 0;
sort(v,v+now);
sort(s+1,s+n+1,cmp);
s[n+1].x1=s[n+1].x2=x;
s[n+1].h=y;
len = unique(v,v+now)-v;
build(1,len,1);
for(int i=1;i<=n+1;i++) {
int l = lower_bound(v,v+len,s[i].x1)-v+1;
int r = lower_bound(v,v+len,s[i].x2)-v+1;
int k = quriy(1,len,1,l);
if(s[i].h-s[k].h>Max) nex[i][0] = -1;
else nex[i][0] = k;
k = quriy(1,len,1,r);
if(s[i].h-s[k].h>Max) nex[i][1] = -1;
else nex[i][1] = k;
modify(1,len,1,l,r,i);
}
// printf("?\n");
int ans = inf;
for(int i=n+1;i>=1;i--) {
int tx1 = nex[i][0];
int tx2 = nex[i][1];
if(tx1!=-1) {
if(tx1!=0) {
dp[tx1][0] = min(dp[tx1][0],dp[i][0] + s[i].x1 - s[tx1].x1);
dp[tx1][1] = min(dp[tx1][1],dp[i][0] + s[tx1].x2 - s[i].x1);
}
else ans = min(ans,dp[i][0]+y);
}
if(tx2!=-1) {
if(tx2!=0) {
dp[tx2][0] = min(dp[tx2][0],dp[i][1] + s[i].x2 - s[tx2].x1);
dp[tx2][1] = min(dp[tx2][1],dp[i][1] + s[tx2].x2 - s[i].x2);
}
else ans = min(ans,dp[i][1]+y);
}
//printf("%d %d %d\n", i,dp[i][0],dp[i][1]);
}
printf("%d\n",ans);
}
return 0;
}