#include #include #include using namespace std; const int N = 2e5 + 1000; // 快读 int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); } return x * f; } // zkw线段树 int d[N << 2]; int n; // n个叶子节点 int q; // q个操作,区间查询或单点修改 int m; // m是指所有父节点们的个数 //单点修改并psuhup void modify(int x, int c) { d[m + x] = c; for (int i = (m + x) >> 1; i; i >>= 1) d[i] = max(d[i << 1], d[i << 1 | 1]); } //构建重口味树 void built() { memset(d, 0, sizeof d); for (m = 1; m <= n + 1;) m <<= 1; // 强行开够(大于n)方便二进制访问叶节点 for (int i = 1; i <= n; i++) d[m + i] = read(); //初始值 for (int i = m; i; i--) d[i] = max(d[i << 1], d[i << 1 | 1]); //待所有叶子节点有值后,统一执行一次向上数据统计信息汇总 } //区间查询 int query(int l, int r) { int ans = -1; // 闭区间改为开区间:l=l+m-1 : 将查询区间改为l-1, r=r+m+1 : 将查询区间改为r+1 // l^r^1 : 相当于判断l与r是否是兄弟节点 for (l = l + m - 1, r = r + m + 1; l ^ r ^ 1; l >>= 1, r >>= 1) { if (~l & 1) ans = max(ans, d[l ^ 1]); // l % 2 == 0 左端点 是左儿子 max(右子树),想像一下题解中0号端点(哨兵),肯定是%2=0 if (r & 1) ans = max(ans, d[r ^ 1]); // r % 2 == 1 右端点 是右儿子 max(左子树),想像一下题解中1号端点,肯定是%2=1 } return ans; } //方法重载,单点查询 [本题没有用到,用来做模板的] int query(int x) { return d[m + x]; //直接返回结果的zkw线段树节点值 } int main() { //文件输入输出 #ifndef ONLINE_JUDGE freopen("HDU1754.in", "r", stdin); #endif char op[2]; while (~scanf("%d%d", &n, &q)) { //构建zkw树 built(); while (q--) { scanf("%s", op); int l = read(), r = read(); if (op[0] == 'Q') printf("%d\n", query(l, r)); else modify(l, r); } } return 0; }