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;
}