Problem:
Score : 1000 points

Problem Statement

Ringo has a string S.

He can perform the following N kinds of operations any number of times in any order.

Operation i: For each of the characters from the L_i-th through the R_i-th characters in S, replace it with its succeeding letter in the English alphabet. (That is, replace a with b, replace b with c and so on.) For z, we assume that its succeeding letter is a.

Ringo loves palindromes and wants to turn S into a palindrome.
Determine whether this is possible.

Constraints

1 \leq |S| \leq 10^5

S consists of lowercase English letters.

1 \leq N \leq 10^5

1 \leq L_i \leq R_i \leq |S|

Input

Input is given from Standard Input in the following format:

S
N
L_1 R_1
L_2 R_2
:
L_N R_N

Output

Print YES if it is possible to turn S into a palindrome; print NO if it is impossible.

Sample Input 1

bixzja
2
2 3
3 6

Sample Output 1

YES

For example, if we perform Operation 1, 2 and 1 in this order, S changes as bixzja → bjyzja → bjzakb → bkaakb and becomes a palindrome.

Sample Input 2

abc
1
2 2

Sample Output 2

NO

Sample Input 3

cassert
4
1 2
3 4
1 1
2 2

Sample Output 3

YES

Solution in C++ (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

#include <bits/stdc++.h>
using namespace std;
#define MOD @
#define ADD(X,Y) ((X) = ((X) + (Y)) % MOD)
typedef long long i64; typedef vector<int> ivec; typedef vector<string> svec;

char S_[101010];
int N, L[101010], R[101010];
int S[101010];
int D[101010];

const int W = 26;

int uf[101010];
int root(int p)
{
	return uf[p] < 0 ? p : (uf[p] = root(uf[p]));
}
void join(int p, int q)
{
	p = root(p); q = root(q);
	if (p == q) return;
	uf[p] += uf[q];
	uf[q] = p;
}

vector<int> grps[101010];

struct data
{
	int sum;
	set<int> *pos, *neg;

	int toppos() const {
		if (pos->empty()) return 1000000;
		return *(pos->begin());
	}
	int topneg() const {
		if (neg->empty()) return 1000000;
		return *(neg->begin());
	}
	int top() const {
		return min(toppos(), topneg());
	}
	int size() const {
		return pos->size() + neg->size();
	}
	bool isneg() const {
		int a = toppos();
		int b = topneg();
		return a > b;
	}
	data(int sum, set<int> *pos, set<int> *neg) : sum(sum), pos(pos), neg(neg) {}
};

inline bool operator<(const data& a, const data& b) {
	return a.top() < b.top() || (a.top() == b.top() && (i64)a.pos < (i64)b.pos);
}

set<data> eqs;

void waf(set<int> *pos, set<int> *neg, int v)
{
	// add v as positive
	if (neg->count(v)) {
		neg->erase(v);
	} else {
		pos->insert(v);
	}
}

data mgr(data a, data b)
{
	if (a.size() < b.size()) swap(a, b);
	bool an = a.isneg(), bn = b.isneg();
	bool neg = an == bn;
	if (neg) {
		a.sum = (a.sum + W - b.sum) % W;
		for (int p : *b.neg) {
			waf(a.pos, a.neg, p);
		}
		for (int p : *b.pos) {
			waf(a.neg, a.pos, p);
		}
	} else {
		a.sum = (a.sum + b.sum) % W;
		for (int p : *b.pos) {
			waf(a.pos, a.neg, p);
		}
		for (int p : *b.neg) {
			waf(a.neg, a.pos, p);
		}
	}
	return a;
}

void show(const data& d) {
	printf("s=%d pos=", d.sum);
	for (int p : *d.pos) printf("%d,", p);
	printf(" neg=");
	for (int p : *d.neg) printf("%d,", p);
	puts("");
}

int main()
{
	scanf("%s%d", S_, &N);
	int M = strlen(S_);
	for (int i = 0; i < M + 3; ++i) uf[i] = -1;
	for (int i = 0; i < N; ++i) {
		scanf("%d%d", L + i, R + i);
		--L[i];

		join(L[i], R[i]);
	}
	S[0] = S[M + 2] = 0;
	for (int i = 0; i < M; ++i) S[i + 1] = S_[i] - 'a';

	for (int i = 0; i <= M; ++i) {
		D[i] = (S[i + 1] - S[i] + W) % W;
	}
	M += 1;
	for (int i = 0; i < M; ++i) {
	//	printf("%d\n", D[i]);
		grps[root(i)].push_back(i);
	}
	for (int i = 0; i < M; ++i) if (grps[i].size() > 0) {
		int sum = 0;
		set<int> *pos = new set<int>, *neg = new set<int>;
		for (int p : grps[i]) {
			if (p * 2 + 1 == M) {
				sum = (sum + D[p]) % W;
				continue;
			}
			if (p >= M / 2) {
				waf(neg, pos, M - 1 - p);
				sum = (sum + D[p]) % W;
			}
			else {
				waf(pos, neg, p);
				sum = (sum + D[p]) % W;
			}
		}
	//	show(data(sum, pos, neg));
		eqs.insert(data(sum, pos, neg));
	}
	while (!eqs.empty()) {
		data top = *(eqs.begin());
		eqs.erase(eqs.begin());

		if (top.top() == 1000000) {
			if (top.sum != 0) {
				puts("NO");
				return 0;
			}
			continue;
		}
		if (eqs.empty()) break;

		if (eqs.begin()->top() != top.top()) {
			continue;
		}

		data top2 = *(eqs.begin());
		eqs.erase(eqs.begin());
		data nw = mgr(top, top2);
		eqs.insert(nw);
	}

	puts("YES");

	return 0;
}