Test instructions: (Chinese test instructions)
Https://codechef_shared.s3.amazonaws.com/download/translated/MARCH15/mandarin/STRSUB.pdf
Analytical:
Preprocessing an array pre[],pre[i] represents the position of I, where it is possible to find a position that satisfies 0 and 1 is not less than K.
Then the length of each position I is the left interval can be calculated, for (R-pre[i] + 1)
Use this in preprocessing a prefix and array dp[].
Dp[i] means: From 1 to i how many substrings are the conditions given to the subject of satisfaction.
Note: pre[] This array is definitely incrementing this is easy to prove.
Dp[i] = dp[i-1] + (I-pre[i] + 1);
(I-pre[i] + 1) is the length of the left interval
And then every time I ask for an interval [L, R]
Using two points in the pre[] array to find a position pos, indicating that the POS to r position between the Pre[i] is greater than L, where pre[] is a monotonically increasing sequence, this can be proved.
Then the number of this part can be calculated, for Dp[r]-dp[pos-1].
Here you may ask, why not directly calculate Dp[r]-DP[L-1]
Because L~pos in the dp[i] may be less than the portion of L also calculated, so that many calculations.
So for the number of L to POS, since this part of the pre is all greater than L,
So the number of each position in this section is (i-l + 1)
So this part of the calculation is a arithmetic progression before the N project and.
1 + 2 + 3 + 4 + ... + pos-l
Arithmetic progression can be preprocessed or calculated directly using formulas.
Two parts and add up is the answer to each question.
AC Code
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>using namespace STD;typedef Long LongllConst intINF =0x3f3f3f3f;Const intN =1e5+Ten;intPre[n];CharStr[n];ll S[n], dp[n];voidGetS () {s[0] =0; for(inti =1; i < N; i++) S[i] = s[i-1] + i;}///two points to find the first satisfying Pre[pos] greater than L positionintFindintLintR) {intLo = L; r++; while(L < R) {intM = L + (r-l)/2;if(Pre[m] < lo) L = m+1;ElseR = M; }returnL;}intMain () {GetS ();intTintN, K, q;scanf("%d", &t); while(t--) {scanf("%d%d%d", &n, &k, &q);scanf('%s ', str+1);intone =0, zero =0, left = n+1; for(inti = n; I >=1; i--) {//Find out the left interval of I while(One <= k && Zero <= K && left >0) {left--;if(Str[left] = =' 0 ') zero++;Elseone++; } Pre[i] = left+1;if(Str[i] = =' 0 ') zero--;Elseone--; }//dp[i] Indicates the number of all the sub-ranges that are met by the current Idp[0] =0; for(inti =1; I <= N; i++) Dp[i] = dp[i-1] + (i-pre[i]+1);intL, R; while(q--) {scanf("%d%d", &l, &r);intpos = Find (L, R); ll ans = dp[r]-dp[pos-1]; Ans + = s[pos-l];printf("%lld\n", ans); } }return 0;}
Codechef Strsub (dp+ two points)