点修改,区间查询。可以用线段树,也可以用Spaly树。用来练习Spaly树吧。。学习Splay树的话推荐一个博客:点击打开链接。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int N = 201000;
const int INF = 0x3f3f3f3f;
int pre[N], key[N], ch[N][2], root, res[N];
//分别表示父结点,键值,左右孩子(0左1右),根结点
//新建一个结点
void NewNode(int r, int val)
{
pre[r] = r - 1;
res[r] = key[r] = val;
ch[r][0] = ch[r][1] = 0;
ch[r - 1][1] = r;
}
void Push_Up(int x)
{
res[x] = max(res[ch[x][0]], res[ch[x][1]]);
res[x] = max(res[x], key[x]);
}
//旋转,kind为1是右旋,为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;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
Push_Up(y);
}
//Splay调整,将结点r调整到goal下面
void Splay(int r, int goal)
{
while(pre[r] != goal)
{
if(pre[pre[r]] == goal) Rotate(r, ch[pre[r]][0] == r);
else
{
int y = pre[r];
int kind = ch[pre[y]][0] == y;
if(ch[y][kind] == r)
{
Rotate(r, !kind);
Rotate(r, kind);
}
else
{
Rotate(y, kind);
Rotate(r, kind);
}
}
}
if(goal == 0) root = r;
}
void Update(int r, int val)
{
Splay(r, 0);
key[r] = val;
Push_Up(r);
}
int Query(int l, int r)
{
Splay(l - 1, 0);
Splay(r + 1, l - 1);
return res[ch[r + 1][0]];
}
int main()
{
int n, m, v, q;
char c[2];
while(scanf("%d%d", &n, &m) != EOF)
{
NewNode(1, -INF);
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 --)
Push_Up(i);
root = 1;
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;
}