马拉车也是可以做的而且复杂度更优。我还是菜啊没有看出来单调性,这个取反翻转操作是单调的,你一个大的串如果是反对称串,中间的任何一个也肯定是啊因为翻转的位置并没有变...那么枚举起点,二分子串长度判断即可,然后比较坑的就是答案要用longlong存。复杂度。因为取反后翻转这个操作,所以不可能有奇数串符合条件(奇数串取反后翻转了一定不相等)
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; typedef long long ll; const int N = 500010; const ull base = 13131; ull h1[N], h2[N], p[N]; int n;ll ans = 0; char s[N]; ull get_h1(int l, int r) { return h1[r] - h1[l - 1] * p[r - l + 1]; } ull get_h2(int l, int r) { return h2[l] - h2[r + 1] * p[r - l + 1]; } int check(int x) { int l = 1, r = min(x, n - x); while(l <= r) { int mid = (l + r) >> 1; if(get_h1(x - mid + 1, x) == get_h2(x + 1, x + mid)) l = mid + 1; else r = mid - 1; } return r; } int main() { scanf("%d%s", &n, s + 1); p[0] = 1; for(int i = 1; i <= n; ++i) p[i] = p[i - 1] * base, h1[i] = h1[i - 1] * base + (ull)s[i]; for(int i = n; i; --i) h2[i] = h2[i + 1] * base + (ull)(s[i] == '0' ? s[i] + 1 : s[i] - 1); for(int i = 1; i < n; ++i) ans += check(i); printf("%lld\n", ans); }