[YNOI2017]由乃的商場之旅 莫隊
阿新 • • 發佈:2018-12-10
Description 給你一個字串,每次給一個詢問,問這個區間內有多少個子串經過重新排序後可以變成一個迴文串。
Sample Input 6 6 zzqzzq 1 6 2 4 3 4 2 3 4 5 1 1
Sample Output 16 4 2 2 3 1
考慮莫隊,因為字元只有26個考慮把他壓成二進位制。 那麼你就可以列舉每個位不一樣,統計答案。 然後其實狀態數是有限的,於是你預處理一下即可。。。
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int read() { int s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar(); return s * f; } struct hh { int x, id; } s[61000]; struct node { int l, r, id, bl; } q[61000]; int m; int sl[61000], sr[61000]; int sum, ans[61000], S[61000], oo[61000], hg[61000][27]; char ss[61000]; bool cmp(node a, node b) { if(a.bl == b.bl) return a.r < b.r; return a.bl < b.bl; } bool cmp1(hh a, hh b) {return a.x < b.x;} void jiar(int x) { int y = S[x]; sl[S[x - 1]]++; sr[y]++; sum += sl[y]; for(int i = 1; i <= hg[x][0]; i++) sum += sl[hg[x][i]]; } void jianr(int x) { int y = S[x]; sr[y]--; sum -= sl[y]; for(int i = 1; i <= hg[x][0]; i++) sum -= sl[hg[x][i]]; sl[S[x - 1]]--; } void jial(int x) { int y = S[x - 1]; sl[y]++; sr[S[x]]++; sum += sr[y]; for(int i = 1; i <= hg[x - 1][0]; i++) sum += sr[hg[x - 1][i]]; } void jianl(int x) { int y = S[x - 1]; sl[y]--; sum -= sr[y]; for(int i = 1; i <= hg[x - 1][0]; i++) sum -= sr[hg[x - 1][i]]; sr[S[x]]--; } int main() { int n = read(), m = read(); scanf("%s", ss + 1); int p = sqrt(m); for(int i = 1; i <= n; i++) { int o = ss[i] - 'a'; s[i].id = i; s[i].x = s[i - 1].x ^ (1 << o); } s[n + 1].x = 0; s[n + 1].id = 0; sort(s + 1, s + n + 2, cmp1); int tp = 0; for(int i = 1; i <= n + 1; i++) { if(s[i].x != s[i - 1].x || i == 1) tp++; S[s[i].id] = tp; oo[tp] = s[i].x; } for(int i = 0; i <= n; i++) { int hh = oo[S[i]]; for(int j = 0; j < 26; j++) { int yy = hh ^ (1 << j); int l = 1, r = n + 1, ans; while(l <= r) { int mid = (l + r) / 2; if(s[mid].x <= yy) l = mid + 1, ans = mid; else r = mid - 1; } if(s[ans].x == yy) hg[i][++hg[i][0]] = S[s[ans].id]; } } for(int i = 1; i <= m; i++) { q[i].l = read(), q[i].r = read(), q[i].id = i; q[i].bl = (q[i].l - 1) / p + 1; } sort(q + 1, q + m + 1, cmp); int ll = 1, rr = 0; sum = 0; for(int i = 1; i <= m; i++) { for(int j = rr + 1; j <= q[i].r; j++) jiar(j); for(int j = rr; j > q[i].r; j--) jianr(j); for(int j = ll; j < q[i].l; j++) jianl(j); for(int j = ll - 1; j >= q[i].l; j--) jial(j); ll = q[i].l, rr = q[i].r; ans[q[i].id] = sum; } for(int i = 1; i <= m; i++) printf("%d\n", ans[i]); return 0; }