这是第一次写斜率优化DP= =。具体的做法参照周源论文《浅谈数形结合思想在信息学竞赛中的应用》。这里仅提供一下AC的代码。
有两点值得注意:1.我这个队列的front和back都是闭区间的;2.在while(...) front++; 这个循环里面,<=写成<就会WA,不知道是为何(讲道理是肯定没问题的,至多多判断几个点而已,我猜想可能是存在了精度误差导致的)。。
代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <math.h> 5 using namespace std; 6 const int N = 1e5 + 100; 7 8 int n,m; 9 int pre[N]; 10 char s[N]; 11 int que[N]; 12 double cal(int x,int y) 13 { 14 return 1.0 * (pre[y] - pre[x]) / (y - x); 15 } 16 17 int main() 18 { 19 int T; 20 scanf("%d",&T); 21 while(T--) 22 { 23 scanf("%d%d",&n,&m); 24 scanf("%s",s+1); 25 for(int i=1;i<=n;i++) pre[i] = pre[i-1] + s[i] - '0'; 26 int front = 0, back = -1; 27 int ansl = 0, ansr = m; 28 double ans = cal(0, m); 29 int len = m; 30 for(int i=m;i<=n;i++) 31 { 32 int a = i - m; 33 while(front < back && cal(que[back], a) <= cal(que[back-1], a)) back--; 34 que[++back] = a; 35 while(front < back && cal(que[front], i) <= cal(que[front+1], i)) front++; 36 double temp = cal(que[front], i); 37 if(temp > ans) 38 { 39 ans = temp; 40 ansl = que[front]; 41 ansr = i; 42 len = i - que[front]; 43 } 44 else if(fabs(temp-ans) < 1e-8 && len > i - que[front]) 45 { 46 len = i - que[front]; 47 ansl = que[front]; 48 ansr = i; 49 } 50 } 51 printf("%d %d\n",ansl + 1, ansr); 52 } 53 return 0; 54 }