Another Problem on Strings CodeForces - 165C
考察:前缀和+二分+双指针
补一个大佬的神级解法 Go
错误思路:
纯双指针处理,写了几个小时没写出来.....
思路:
前缀和预处理,sum[i]表示1~i坐标有多少个1,那么[l,r]区间内1的个数为sum[r] - sum[l-1],那么我们可以枚举端点,计算[l,r]区间里有多少个1,如果==k,ans++.
以上为暴力思路,根据数据我们还需要优化.一般优化第二层循环.枚举左端点,找到==sum[i]+k的sum[j]和>sum[i]+k的sum[r],[j,r)之间都为答案.
但是要特判k = 0,这里本蒟蒻用的双指针处理.
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int N = 1000010; 8 int k,sum[N]; 9 char s[N]; 10 LL ans; 11 int main() 12 { 13 scanf("%d%s",&k,s+1); 14 int len = strlen(s+1),cnt = 0; 15 for(int i=1;i<=len;i++) sum[i] = sum[i-1]+(s[i]-'0'); 16 if(!k) 17 { 18 for(int i=1,j=1;i<=len;i++) 19 { 20 int t = s[i]-'0'; 21 if(t) continue; 22 if(j<i) j = i; 23 while(j<=len&&s[j]=='0') j++; 24 ans+=(LL)(j-i); 25 } 26 printf("%I64d\n",ans); 27 return 0; 28 } 29 for(int i=0;i<len;i++) 30 {//sum[l~r]-sum[i] = k 31 int l = lower_bound(sum+1,sum+len+1,sum[i]+k)-sum; 32 int r = upper_bound(sum+1,sum+len+1,sum[i]+k)-sum; 33 if(l==len+1) break;//当l==len+1,r一定==len+1,r-l==0; 34 ans+=(LL)(r-l); 35 } 36 printf("%I64d\n",ans); 37 return 0; 38 }