【思维】2021牛客暑期多校训练营5 C Cheating and Stealing
2021-09-07 21:06:00
# ACM
题链
题目解析 当局分为 $i$,局数是 $O(n/i)$ 的,如果可以 $O(1)$ 地处理每一局,那么复杂度是 $O(nlogn)$ 的;
具体思路为记录前缀数组: $qz[1][i]$ 表示 $W$ 的前缀和; $qz[0][i]$ 表示 $L$ 的前缀和; 记录位置数组: $pos[1][i]$ 表示第 $i$ 个 $W$ 所在位置; $pos[0][i]$ 表示第 $i$ 个 $L$ 所在位置; 那么就可以 $O(1)$ 地找到某个位置后面第 $k$ 个 $W$ 或 $L$ 的位置; $pos[sum[i-1] + k]$
如果出现平分也就是 $\vert cntW-cntL \vert <= 1$ 的情况,就是需要知道从第 $i$ 轮开始,到第几轮才会打破平均; $p[i]$ 表示从第 $i$ 局开始什么时候打破平局; $p[i] = (s[i] == s[i+1])?i+1:p[i+2]$;
代码实现 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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 #include <bits/stdc++.h> using namespace std; #define LL long long #define ls rt<<1 #define rs rt<<1|1 #define eps 1e-6 #define mod 998244353 #define MAXN 1e9 #define MS 1000009 int n,m;char s[MS];int qz[2 ][MS];int pos[2 ][MS], cnt[2 ];int p[MS];int f[MS];int a[MS];void init () { a[1 ] = 1 ; for (int i=2 ;i<=n;i++){ a[i] = (LL)a[i-1 ]*(LL)(n+1 )%mod; } } int jdg (int l,int x) { int r1 = n+1 , r2 = n+1 ; if (qz[1 ][n] - qz[1 ][l-1 ] >= x){ r1 = pos[1 ][ qz[1 ][l-1 ] + x ]; } if (qz[0 ][n] - qz[0 ][l-1 ] >= x){ r2 = pos[0 ][ qz[0 ][l-1 ] + x ]; } int r = min (r1, r2); if (r > n) return 0 ; int cnt1 = qz[1 ][r] - qz[1 ][l-1 ]; int cnt2 = qz[0 ][r] - qz[0 ][l-1 ]; if (abs (cnt1-cnt2) >= 2 ){ if (cnt1 > cnt2) f[x]++; return r+1 ; } else { if (cnt1 == cnt2) r = p[r+1 ]; else r = p[r]; if (r == -1 ) return 0 ; else { cnt1 = qz[1 ][r] - qz[1 ][l-1 ]; cnt2 = qz[0 ][r] - qz[0 ][l-1 ]; if (cnt1 > cnt2) f[x]++; return r+1 ; } } } void cal (int x) { int l = 1 ; while (l < n && l){ l = jdg (l,x); } } void solve () { cin >> n; init (); cin >> s+1 ; for (int i=1 ;i<=n;i++){ if (s[i] == 'W' ){ qz[1 ][i] = qz[1 ][i-1 ] + 1 ; qz[0 ][i] = qz[0 ][i-1 ]; pos[1 ][++cnt[1 ]] = i; } else if (s[i] == 'L' ){ qz[0 ][i] = qz[0 ][i-1 ] + 1 ; qz[1 ][i] = qz[1 ][i-1 ]; pos[0 ][++cnt[0 ]] = i; } } p[n] = p[n+1 ] = -1 ; for (int i=n-1 ;i>=1 ;i--){ if (s[i] == s[i+1 ]) p[i] = i+1 ; else p[i] = p[i+2 ]; } for (int i=1 ;i<=n;i++){ cal (i); } LL ans = 0 ; for (int i=1 ;i<=n;i++){ ans += (LL)f[i]*(LL)a[i]%mod; ans %= mod; } cout << ans%mod << "\n" ; } int main () { ios::sync_with_stdio (false ); int ce; ce = 1 ; while (ce--){ solve (); } return 0 ; }
2021-09-07 21:06:00
# ACM