1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include  <bits/stdc++.h>  using  namespace  std;int  main ()      int  J;     cin >> J;          while  (J--) {         int  n;         cin >> n;         cout << (n / 15  * 3  + min (n % 15 , 2 ) + 1 ) << endl;     }          return  0 ; } 
仔细审题 
题解 分为两部分考虑,从起点走到 0,从 0 下一次走到 0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include  <bits/stdc++.h>  using  namespace  std;using  ll = long  long ;int  main ()      int  J;     cin >> J;          while  (J--) {         int  n, t;         ll k;         cin >> n >> t >> k;         string s;         cin >> s;         ll res = 0 ;         int  x = t;         for  (auto  c : s) {             if  (c == 'L' ) x--;             else  x++;             k--;             if  (x == 0 ) {                 res++;                 break ;             }             if  (k == 0 ) {                 break ;             }         }         if  (k == 0  || x) {             cout << res << endl;             continue ;         }            assert (x == 0 );         int  cnt = 0 ;         for  (auto  c : s) {             if  (c == 'L' ) x--;             else  x++;             cnt++;             if  (x == 0 ) {                 break ;             }         }         if  (x == 0 ) res += k / cnt;         cout << res << endl;     }          return  0 ; } 
所求是最大值最小问题,可以用什么方法? 二分答案。
问题转化为,⩾ x \geqslant x ⩾ x < x <x < x k k k 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include  <bits/stdc++.h>  using  namespace  std;int  main ()      int  J;     cin >> J;          while  (J--) {         int  n, k;         cin >> n >> k;         string s;         cin >> s;         vector<int > a (n)  ;         for  (int  i = 0 ; i < n; i++) {             cin >> a[i];         }         auto  check = [&](int  mid) {             string b;             for  (int  i = 0 ; i < n; i++) {                 if  (a[i] > mid) {                     b += s[i];                   }             }             int  cnt = 0 ;             int  res = 0 ;             for  (int  i = 0 ; i < b.size (); i++) {                 if  (b[i] == 'R' ) {                     if  (cnt) res++;                       cnt = 0 ;                 } else  {                     cnt++;                 }             }             if  (cnt) res++;             return  res <= k;         };         int  l = 0 , r = 1e9  + 8 ;;         while  (l <= r) {             int  mid = l + r >> 1 ;             if  (check (mid)) {                 r = mid - 1 ;             } else  {                 l = mid + 1 ;             }         }         cout << l << endl;     }          return  0 ; } 
写复杂了。正着转移简单一些,这里就不细讲我的思路了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include  <bits/stdc++.h>  using  namespace  std;using  ll = long  long ;constexpr  ll mod = 998244353 ;int  main ()      int  J;     cin >> J;          while  (J--) {         int  n;         cin >> n;         vector<vector<int >> dis (n);         vector<vector<int >> E (n);         vector<int > d (n)  ;         for  (int  i = 1 ; i < n; i++) {             int  p;             cin >> p;             p--;             E[p].push_back (i);             d[i] = d[p] + 1 ;             dis[d[i]].push_back (i);         }         vector<int > dp (n)  ;         vector<int > sum (n + 1 )  ;         for  (int  i = n - 1 ; i > 0 ; i--) {             for  (auto  u : dis[i]) {                 dp[u] = sum[i + 1 ] + 1 ;                 dp[u] %= mod;                 for  (auto  v : E[u]) {                     dp[u] -= dp[v];                     dp[u] %= mod;                     dp[u] += mod;                     dp[u] %= mod;                 }             }             for  (auto  u : dis[i]) {                 sum[i] += dp[u];                 sum[i] %= mod;             }         }         ll res = 1 ;         for  (auto  u : E[0 ]) {             res += dp[u];             res %= mod;         }         cout << res << endl;     }          return  0 ; } 
后手优先选 10(含 01),这样就是双方 00 - 10 - 00 ... 交替选择。先手何时必胜? 称先后手各操作一次为一轮。每轮操作 0 的个数 -3,1 的个数 -1。如此操作直到取不满一轮。
如果剩下没有 1,那有足够多的 0 先手便胜利,即c 0 ⩾ 2 , c 1 = 0 c_{0} \geqslant 2,c_{1}=0 c 0  ⩾ 2 , c 1  = 0 q q q c 0 − 2 ⩾ 3 c 1 c_{0}-2 \geqslant 3c_{1} c 0  − 2 ⩾ 3 c 1  
如果剩下一个 1,那只有 0 的数量为 2 时先手胜利,即c 0 = 2 , c 1 = 1 c_{0}=2,c_{1}=1 c 0  = 2 , c 1  = 1 q q q c 0 − 2 = 3 c 1 − 1 c_{0}-2 = 3c_{1}-1 c 0  − 2 = 3 c 1  − 1 
0 1 数量都是 3 倍关系,考虑给 0 赋一个权值 1,给 1 赋一个权值 -3,进一步简化条件。 给 0 赋一个权值 1,给 1 赋一个权值 -3。于是区间权值和为c 0 − 3 c 1 c_{0}-3c_{1} c 0  − 3 c 1  
结合刚才得到的结论,区间权值和w ⩾ 2 w \geqslant 2 w ⩾ 2 w = − 1 w=-1 w = − 1 
回忆这样的问题:给定序列,问有多少子区间的和为 0。 将区间和转为前缀和,对于本题是s r − 2 ⩾ s l s_{r} -2\geqslant s_{l} s r  − 2 ⩾ s l  s r + 1 = s l s_{r}+1=s_{l} s r  + 1 = s l  
用桶存s l s_{l} s l  
第二个式子是等式,直接从桶里拿。
第一个式子是不等式,需要一个辅助指针p p p ⩽ \leqslant ⩽ 
1 2 3 4 5 6 7 8 9 10 while  (p < s[r] - 2 ) {    p++;     sum += mp[p]; } while  (p > s[r] - 2 ) {    sum -= mp[p];     p--; } res += sum; 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include  <bits/stdc++.h>  using  namespace  std;using  ll = long  long ;int  main ()      int  n;     cin >> n;     string s;     cin >> s;     int  pre = 0 ;     map<int , int > mp;     mp[0 ] = 1 ;     ll res = 0 ;     int  sum = 0 ;     int  p = -1 ;     for  (int  i = 0 ; i < n; i++) {         int  x = s[i] == '0'  ? 1  : -3 ;         pre += x;                  res += mp[pre + 1 ];                  while  (p < pre - 2 ) {             p++;             sum += mp[p];         }         while  (p > pre - 2 ) {             sum -= mp[p];             p--;         }                  res += sum;         mp[pre]++;         if  (p >= pre) {             sum++;         }     }     cout << res << endl;          return  0 ; }