La idea es un segment tree. Muy overkill, teniendo en cuenta que el string no se modifica un sparse data table habría sido más que suficiente, pero bueno, AC is AC.
También decir que lo de dar el input con un formato de mierda es cancerígeno.
#include <bits/stdc++.h>
#pragma GCC optimize ("O2")
using namespace std;
const int inf = 1e8;
struct node{
int min,max;
};
node tree[1<<21];
void setPos(int pos, int val, int l, int r, int id){
if(pos<l or pos>r) return;
if(l==r and pos==l) tree[id].min = tree[id].max = val;
else{
setPos(pos, val, l, (l+r)/2, 2*id), setPos(pos, val, (l+r)/2 + 1, r, 2*id + 1);
tree[id].min = min(tree[2*id].min, tree[2*id + 1].min);
tree[id].max = max(tree[2*id].max, tree[2*id + 1].max);
}
}
pair<int,int> rmq(int ql, int qr, int l, int r, int id){
if(qr<l or ql>r) return make_pair(inf, -inf);
if(l>=ql and r<=qr) return make_pair(tree[id].min, tree[id].max);
int m = (l+r)/2;
pair<int,int> retl = rmq(ql, qr, l, (l+r)/2, 2*id);
pair<int,int> retr = rmq(ql, qr, (l+r)/2 + 1, r, 2*id + 1);
return make_pair(min(retl.first,retr.first), max(retl.second, retr.second));
}
bool query(int ql, int qr, int l, int r, int id){
pair<int,int> ans = rmq(ql, qr, l, r, id);
return ans.first == ans.second;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
string T;
while(getline(cin,T)){
int n = (int)T.size();
//los espacios cuentan? vaya mierda de samples...
for(int i=0; i<n; ++i)
setPos(i+1, T[i], 1, n, 1);
string line;
int Q; getline(cin,line); Q = atoi(line.c_str());
if(Q==0) return 0;
while(Q--){
int l,r;
getline(cin,line);
istringstream ss(line);
ss >> l >> r; ++l, ++r;
if(l>r) swap(l,r); //dar mal los queries dejo de tener gracia en 2002...
cout << (query(l,r,1,n,1) ? "SI" : "NO") << "\n";
}
cout << "\n";
}
}