首先,要说明滑动队列优化的情形,必须是当前位置前或者后面的一个连续区间的一个和 j 相关的func值。
维护的队列为一个相对有保留价值序列,如本题维护的是func值上升而里该节点的远度下降(这也是func较低而又保留价值的原因)。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <climits>
#include <deque>
using namespace std;
const int maxn = 101000;
int n,c,sum[maxn],dist[maxn],d[maxn];
int x[maxn],y[maxn],w[maxn];
int dis(int i,int j){
return abs(x[i]-x[j])+abs(y[i]-y[j]);
}
int func(int j){
return d[j]+sum[j]+dist[j];
}
deque<int> Q;
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d %d",&c,&n);
x[0] = y[0] = sum[0] = w[0] =0;
for(int i=1;i<=n;i++){
int z;
scanf("%d %d %d",&x[i],&y[i],&z);
sum[i]=sum[i-1]+dis(i-1,i);
w[i] = w[i-1]+z;
dist[i] = dis(0,i);
}
while(!Q.empty()) Q.pop_back();
d[n] = 0;
Q.push_back(n);
for(int i=n-1;i>=0;i--){
while(!Q.empty()&&w[Q.front()]-w[i]>c) Q.pop_front();
d[i]=func(Q.front())+dist[i+1]-sum[i+1];
while(!Q.empty()&&func(i)<=func(Q.back())) Q.pop_back();
Q.push_back(i);
}
printf("%d\n",d[0]);
if(T)printf("\n");
}
return 0;
}