一开始直接想到了二分,写了一发然后过了全部样例就交了,果断WA。因为这个问题显然是不满足单调性的。
然后想之前刚做的斜率优化DP,但是那个是求斜率最大值,不是求满足斜率大于一定值的最大长度的。也构造不出好的方法。
最后的方法是列个式子:i+1~j位置可以成立仅当 (pre[j] - pre[i]) / (j - i) >= (100-p) / 100。不妨把p变成100-p,再作化简得:
100 * pre[j] - p * j >= 100 * pre[i] - p * i。因此,不妨令val[i] = 100 * pre[i] - p * i。那么以val作为关键字进行排序,只要某个位置序号大于前面的,那么这一段显然就是可以的了。因此,只要线性的扫一遍更新最大值即可。
代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N = 150000 + 5; 6 7 char s1[N], s2[N]; 8 int n,p; 9 int pre[N]; 10 struct node 11 { 12 int val, id; 13 bool operator < (const node & temp) const 14 { 15 return val == temp.val ? id < temp.id : val < temp.val; 16 } 17 }my[N]; 18 19 int main() 20 { 21 while(scanf("%d%d",&n,&p) == 2) 22 { 23 if(n == 0 && p == 0) break; 24 scanf("%s%s",s1+1,s2+1); 25 26 p = 100 - p; 27 for(int i=1;i<=n;i++) pre[i] = pre[i-1] + (s1[i] == s2[i]); 28 for(int i=0;i<=n;i++) my[i].val = 100 * pre[i] - p * i, my[i].id = i; 29 sort(my, my+1+n); 30 int minn = my[0].id; 31 int ans = 0; 32 for(int i=1;i<=n;i++) 33 { 34 if(my[i].id < minn) 35 { 36 minn = my[i].id; 37 } 38 else ans = max(ans, my[i].id - minn); 39 } 40 if(ans != 0) printf("%d ",ans); 41 else puts("No solution."); 42 } 43 return 0; 44 }