水题,Splay做下。建树时直接根据id顺序建树,首尾增加两个节点。询问操作先见l-1旋转至根节点,再将r+1旋转至l-1右节点处。旋转后[l,r]节点都在r+1左子树上。r+1左儿子res值即为所求值。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 200005
#define mod 20140518
const int inf = (1 << 29);
typedef long long LL;
int n, m;
int pre[N], key[N], ch[N][2], root, tot1, res[N];
int cnt[N];
//ch[][0]为左孩子,ch[][1]为右孩子
void NewNode(int r, int val){
ch[r][0] = ch[r][1] = 0;
pre[r] = r - 1;
res[r] = key[r] = val;
ch[r - 1][1] = r;
}
void pushup(int x){
res[x] = max(res[ch[x][0]], res[ch[x][1]]);
res[x] = max(res[x], key[x]);
}
//kind = 1为右旋,kind为0左旋
void Rotate(int x,int kind){
int y = pre[x];
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y]){
ch[pre[y]][ch[pre[y]][1] == y] = x;
}//y节点有父节点用x节点将其替代
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
pushup(y);
}
void Splay(int r, int goal){
while(pre[r] != goal){
int y = pre[r];
int kind = (ch[y][0] == r);
if(pre[y] != goal && (kind == (ch[pre[y]][0] == y))){
Rotate(y, kind);
}
Rotate(r, kind);
}
pushup(r);
if(goal == 0)root = r;
}
void update(int r, int val){
Splay(r, 0);
key[r] = val;
pushup(r);
}
int Query(int l, int r){
Splay(l - 1, 0);
Splay(r + 1, l - 1);
return res[ch[r + 1][0]];
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
NewNode(1, -inf);
int q, v;
for(int i = 1; i <= n; i++){
scanf("%d", &v);
NewNode(i + 1, v);
}
NewNode(n + 2, -inf);
for(int i = n + 2; i; i--){
pushup(i);
}
root = 1;
char c[10];
for(int i = 0; i < m; i++){
scanf("%s%d%d", c, &q, &v);
if(c[0] == 'Q')
printf("%d\n", Query(q + 1, v + 1));
else update(q + 1, v);
}
}
return 0;
}