1. 程式人生 > >[YNOI2017]由乃的商場之旅 莫隊

[YNOI2017]由乃的商場之旅 莫隊

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