5 6 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 2 9 Q 1 5
5 6 5 9HintHuge input,the C function scanf() will work better than cin
建树,点修改,查询。理论知识在本类别其他博客,或查阅相关资料,这里不再赘述。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define Lson 2 * o, L, M //左儿子,这样写减少了代码量,不易出错 #define Rson 2 * o + 1, M + 1, R //ps:开始没有这样写,debug了好久 const int MAXM = 3 * 200000 + 10; //结点总数应略小于区间长度的两倍,这里2*却TLE! int maxV[MAXM]; int ql, qr, p, v; int n, m; //向上更新,由 o 的左右儿子更新 o void PushUp(int o) { maxV[o] = max(maxV[2 * o], maxV[2 * o + 1]); } //建树 void Build(int o, int L, int R) { if (L == R) scanf("%d", &maxV[o]); //叶子结点 else { int M = (L + R) / 2; Build(Lson); //左子树 Build(Rson); //右子树 PushUp(o); //更新 } } //查询区间ql,qr最大值 o为当前结点编号,L为当前结点左端点,R为右端点 int Query(int o, int L, int R) { if (ql <= L && qr >= R) return maxV[o]; //当前结点完全包含在查询区间内 int M = (L + R) / 2; int ans = 0; if (ql <= M) ans = max(ans, Query(Lson)); //往左走,左儿子 if (qr > M) ans = max(ans, Query(Rson)); //往右走,右儿子 return ans; } //修改A[p] = v,这里A为虚拟成绩,我们已经将它保存在maxV中 void Update(int o, int L, int R) { int M = (L + R) / 2; if (L == R) maxV[o] = v;//叶结点,直接修改 else { if (p <= M) Update(Lson); //先递归更新左子树或者右子树 else Update(Rson); PushUp(o); //然后计算本结点的maxV } } int main() { while (~scanf("%d%d", &n, &m)) { memset(maxV, 0, sizeof(maxV)); Build(1, 1, n); char ch[10]; while (m--) { scanf("%s", ch); if (ch[0] == 'Q') { scanf("%d%d", &ql, &qr); printf("%d\n", Query(1, 1, n)); } else { scanf("%d%d", &p, &v); Update(1, 1, n); } } } return 0; }