P3580
至今没搞懂这个题为什么要单调队列……感觉这个题的题解写得都有些【数据删除】。
感觉说这题要有单调队列优化的题解都没搞清楚这题本质。
首先有个重要结论是:火车要么不回,要么一起回。
- 证明:首先如果回来的途中没有阻碍其他火车出现,那全部回来显然更优。那如果某个火车
i 回来时没有阻碍其他火车发车,但是火车i+1 回来时会阻碍到其他火车发车,则每多回来一辆车,后一辆火车多延迟发车1 分钟,但是如果留到最后再回来,也会花费1 的时间,所以让他们一次性回来必然不比先把一部分放回来,最后再全部放回来劣。
根据此,我们考虑设计状态
题目保证了
则易得
对于转移方程中那个
考虑
然后还有一个重要结论:
同时结合我们上面推导的东西,可以得到
复杂度
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define ull unsigned long long
#define ld long double
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define chkmax(a,b) a=max(a,b)
#define chkmin(a,b) a=min(a,b)
#define rep(k,l,r) for(int k=l;k<=r;++k)
#define per(k,r,l) for(int k=r;k>=l;--k)
#define cl(f,x) memset(f,x,sizeof(f))
using namespace std;
const int N=1e6+5;
int f[N],a[N];
signed main() {
int n,s;
scanf("%lld%lld",&n,&s);
a[0]=-1;
rep(i,1,n)
scanf("%lld",&a[i]),chkmax(a[i],a[i-1]+1);
cl(f,0x3f); f[0]=0;
int p=0;
rep(i,1,n) {
while(p<i&&f[p]-p<a[i]-i+1)
++p;
chkmin(f[i],a[i]+2*s+i-(p-1)-1);
if(p!=i)
chkmin(f[i],f[p]+2*(i+s-p-1));
}
printf("%lld\n",f[n]);
return 0;
}