class Log2 {
public:
Log2(int cnt) {
lg.assign(cnt + 1, -1);
for (int i = 1; i <= cnt; i++) {
lg[i] = lg[i - 1] + (i & (i - 1) ? 0 : 1);
}
}
int operator[](int len) {
return lg[len];
}
vector<int> lg;
};
Log2 lg2(maxn);
class STTable {
public:
~STTable() {
qmin.clear();
qmax.clear();
}
public:
void getLg(int len) {
lg2.assign(len + 1, -1);
for (int i = 1; i <= len; i++) {
lg2[i] = lg2[i - 1] + (i & (i - 1) ? 0 : 1);
}
}
void Init(vector<int>& input) {
Init(input.data(), input.size());
}
void Init(int* input,int len) {
getLg(len + 1);
int col2 = lg2[len],flag = 0;
qmin.assign(len + flag, vector<int>(col2 + 1, 0));
qmax.assign(len + flag, vector<int>(col2 + 1, 0));
for (int i = flag; i < len + flag; i++)
qmin[i][0] = qmax[i][0] = input[i - flag];
for (int i = 1; i <= col2; i++) {
for (int j = flag; lg2[len + flag - j] >= i; j++) {
int diff = 1 << (i - 1);
qmin[j][i] = min(qmin[j][i - 1], qmin[j + diff][i - 1]);
qmax[j][i] = max(qmax[j][i - 1], qmax[j + diff][i - 1]);
}
}
}
int getMin(int left, int right) {
int k = lg2[right - left + 1];
return min(qmin[left][k], qmin[right - (1 << k) + 1][k]);
}
int getMax(int left, int right) {
int k = lg2[right - left + 1];
return max(qmax[left][k], qmax[right - (1 << k) + 1][k]);
}
public:
vector<vector<int>> qmin, qmax;
vector<int> lg2;
};