constint N = 2e5 + 10; int v[N],n,q; int stmin[N][22],stmax[N][22]; inlinevoidInit() { for(int i = 1;i <= n;++i) stmin[i][0] = stmax[i][0] = v[i];
for(int j = 1;j <= log2(n);++j) { for(int i = 1;i + (1 << j) - 1 <= n;++i) { int r = i + (1 << j - 1); stmin[i][j] = min(stmin[i][j - 1],stmin[r][j - 1]); stmax[i][j] = max(stmax[i][j - 1],stmax[r][j - 1]); } } } inlineintrmq_min(int L,int R) { int k = log2(R - L + 1); int len = (1 << k); int r = R - len + 1; returnmin(stmin[L][k],stmin[r][k]); } inlineintrmq_max(int L,int R) { int k = log2(R - L + 1); int len = (1 << k); int r = R - len + 1; returnmax(stmax[L][k],stmax[r][k]); }
#include<iostream> #include<vector> #include<queue> #include<cstring> #include<algorithm> #include<cmath> #define endl '\n' #include<unordered_map> #define int long long #define YES puts("YES") #define NO puts("NO") #define umap unordered_map #define All(x) x.begin(),x.end() #pragma GCC optimize(3,"Ofast","inline") #define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0) usingnamespace std; constint N = 2e5 + 10;
// 这是个二维数组 可以理解为 int[][] 其中这个二维数组存储的是 对应的 R 和 r // 其中 一维 int[] 存储的是 原端点 R 二维 int[][] 存储的是 截半右端点 r 至于为何 r 开 22 , // 这个是由于我们 是 log 以 2 为底、长度为基的数值 得到的右端点,所以我们开存在于我们范围内即可 int st_min[N][22],st_max[N][22]; int v[N]; // 存储原数组元素 int n,q;
inlinevoidInit() { // 预处理求出当前点的 右端点 R for(int i = 1;i <= n;++i) { // 这里是 当 左右端点相同的时候 它们的最值等于它们本身 // 即 : L == R 没有截半,截半端点r = 0 st_min[i][0] = st_max[i][0] = v[i]; }
// 开始求每个截半区间的最值 for(int R = 1;R <= log2(n);++R) // 这是区间右端点 R { // 截半区间前提是 截半的右端点 r 区间长度 不超过我们整个数组的区间长度 for(int L = 1;L + (1 << R) - 1 <= n;++L) { int r = L + (1 << R - 1); // 截半右端点的 r