题目
分析
考虑DP,
需要的状态:位置,自己是否发信号
f[i][0/1]表示覆盖到第i台的最少代价
也就是说,只保证了结尾为i及小于i的区间有烽火台
转移:
f[i][0] = min(f[i-m+1][1],f[i-m+2][1],…,f[i-1][1]);
f[i][1] = min(f[i-m][1],f[i-m+1][1],f[i-m+2][1],…,f[i-1][1]);
f[i][1]不能用f[j][0]转移
因为只保证了结尾为i - m + 1及小于i - m + 1的区间有烽火台,而不能保证以 i - m + 1到 i 为结尾的区间有烽火台
好了
接下来,看数据范围
显然不可能暴枚
看,固定区间的最值,
单调队列
代码

1 /************************ 2 User:Mandy.H.Y 3 Language:c++ 4 Problem:luogu 5 Algorithm: 6 Date:2019.9.2 7 ************************/ 8 #include<bits/stdc++.h> 9 10 using namespace std; 11 12 const int maxn = 2e5 + 5; 13 14 int n,m,l1,r1; 15 int a[maxn],f[maxn][3]; 16 int q1[maxn]; 17 18 template<class T>inline void read(T &x){ 19 x = 0;bool flag = 0;char ch = getchar(); 20 while(!isdigit(ch)) flag |= ch == '-',ch = getchar(); 21 while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar(); 22 if(flag) x = -x; 23 } 24 25 template<class T>void putch(const T x){ 26 if(x > 9) putch(x / 10); 27 putchar(x % 10 | 48); 28 } 29 30 template<class T>void put(const T x){ 31 if(x < 0) putchar('-'),putch(-x); 32 else putch(x); 33 } 34 35 void file(){ 36 freopen("10180.in","r",stdin); 37 freopen("10180.out","w",stdout); 38 } 39 40 void readdata(){ 41 read(n);read(m); 42 for(int i = 1;i <= n; ++ i){ 43 read(a[i]); 44 } 45 } 46 47 void work(){ 48 49 f[1][0] = 0x3f3f3f3f; 50 f[1][1] = a[1];//关于1的初始化 51 q1[r1++] = 1; 52 53 for(int i = 2;i <= n;i ++){ 54 55 f[i][0] = 0x3f3f3f3f; 56 if(i <= m) f[i][1] = a[i];//开始还没到m的 57 else f[i][1] = 0x3f3f3f3f; 58 59 while(l1 < r1 && q1[l1] <= i - m) l1++; 60 61 if(i-m > 0) f[i][1] = min(f[i-m][1] + a[i],f[i][1]); 62 if(l1 < r1) f[i][0] = f[q1[l1]][1],f[i][1] = min(f[i][1],f[q1[l1]][1] + a[i]); 63 64 while(l1 < r1 && f[i][1] <= f[q1[r1-1]][1]) r1--; 65 66 q1[r1++] = i; 67 68 } 69 70 put(min(f[n][1],f[n][0])); 71 } 72 73 int main(){ 74 // file(); 75 readdata(); 76 work(); 77 return 0; 78 }