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++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;

struct UnionFind {
    vector<int> par;
    vector<int> sz;

    UnionFind(int n=0){
        if(n>0) initialize(n);
    }

    void initialize(int n){
        par.resize(n);
        sz.resize(n);
        for(int i=0; i<n; i++){
            par[i] = i;
            sz[i] = 1;
        }
    }

    int find(int x){
        if(par[x] == x){
            return x;
        }else{
            return par[x] = find(par[x]);
        }
    }

    void unite(int x, int y){
        x = find(x);
        y = find(y);
        if(x == y) return;
        if(sz[x] > sz[y]) swap(x, y);
        par[x] = y;
        sz[y] += sz[x];
    }

    bool same(int x, int y){
        return find(x) == find(y);
    }

    int size(int x){
        return sz[find(x)];
    }
};

int main(){
    string S;
    int N;
    cin >> S >> N;
    int L = S.size();
    int sz = L/2;
    vector<int> V(sz+2, 0);
    for(int i=1; i<=sz; i++) V[i] = S[i-1] - S[L-i];
    vector<int> diff(sz+1, 0);
    for(int i=0; i<=sz; i++) diff[i] = V[i+1] - V[i];

    UnionFind uf(sz+1);
    for(int i=0; i<N; i++){
        int l, r;
        cin >> l >> r;
        l--;
        l = min(l, L-l);
        r = min(r, L-r);
        uf.unite(l, r);
    }

    vector<int> sum(sz+1, 0);
    for(int i=0; i<=sz; i++) sum[uf.find(i)] += diff[i];
    for(int i=0; i<=sz; i++) if(sum[i] % 26){
        cout << "NO" << endl;
        return 0;
    }
    cout << "YES" << endl;
    return 0;
}