题目
题解
看到1e5有点慌,后来发现是个序列dp,然后依次的曼哈顿距离是可以用前缀和实现优化的,然后发现像个线段树,然后发现可以O(1)更新,然后发现自己完全没管载重C,好像会过期?那不就是单调队列吗。。xjb写写写。好像中间把式子推错了一个,cal里面是-sum[p+1]推成了-sum[p]查了一会儿。(好像斜率优化啊而且斜率优化我也经常推错式子(:зゝ∠) )好像还因为输出格式不对被卡了一会儿。。mdzz
代码
//QWsin
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100000+10;
inline int read()
{
int ret=0,ok=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-')ok=-1;ch=getchar();}
for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
return ret*ok;
}
int C,n,w[maxn],x[maxn],y[maxn];
int sum[maxn],dp[maxn],sumw[maxn];
int Queue[maxn],Ql,Qr;
inline int D(int i){return abs(x[i])+abs(y[i]);}
inline int cal(int p){return dp[p]-sum[p+1]+D(p+1);}
inline void solve()
{
C=read();n=read();
for(int i=1;i<=n;++i)
{
x[i]=read();y[i]=read();w[i]=read();
sumw[i]=sumw[i-1]+w[i];
}
for(int i=2;i<=n;++i) sum[i]=sum[i-1]+abs(x[i-1]-x[i])+abs(y[i-1]-y[i]);
Ql=1;Qr=0;Queue[++Qr]=0;
for(int i=1;i<=n;++i)
{
while(Ql<=Qr&&sumw[i]-sumw[Queue[Ql]] > C) ++Ql;
int p=Queue[Ql];
dp[i]=cal(p)+sum[i]+D(i);
while(Ql<=Qr&&cal(Queue[Qr]) >= cal(i)) --Qr;
Queue[++Qr]=i;
}
printf("%d\n",dp[n]);
}
int main()
{
int T;cin>>T;
while(T--)
{
solve();
if(T) printf("\n");
}
return 0;
}