Splay树除了被用作平衡二叉树之外,还有许多更高级但我们不常用的功能,比如:用Splay的旋转操作来维护区间信息,这里的旋转优先级我们可以用一个Rank来表示,则Rank[i]就代表了第i个点的优先级(对应的就是原来的序列中的位置标号),通过依据对位置标号的旋转操作,我们可以更加方便直观的维护一个区间的总和、最值等信息,并且理论复杂度与线段树相当。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 2000 + 10;
const int INF = 0x3f3f3f3f;
struct SplayTree {
int n, root;
int c[maxn][2], fa[maxn], tid[maxn];
int Val[maxn], Max[maxn], Rank[maxn], size[maxn];
void init() {
n = root = 0;
memset(c, 0, sizeof(c));
memset(fa, 0, sizeof(fa));
memset(tid, 0, sizeof(tid));
memset(Rank, 0, sizeof(Rank));
}
int Newnode(int val, int k) {
++n;
Val[n] = Max[n] = val;
Rank[n] = k; size[n] = 1; tid[k] = n;
return n;
}
void Push_up(int u) {
Max[u] = Val[u];
if(c[u][0]) Max[u] = max(Max[u], Max[c[u][0]]);
if(c[u][1]) Max[u] = max(Max[u], Max[c[u][1]]);
size[u] = size[c[u][0]] + size[c[u][1]] + 1;
}
void rotate(int u) {
int v = fa[u], w = fa[v], t = c[v][1] == u;
fa[c[u][t^1]] = v, c[v][t] = c[u][t^1];
c[u][t^1] = v; fa[u] = w; fa[v] = u;
if(root == v) root = u;
else c[w][c[w][1] == v] = u;
Push_up(v);
}
void Splay(int u, int pos) {
while(fa[u] != pos) {
int v = fa[u], w = fa[v];
if(fa[v] == pos)
rotate(u);
else if((c[v][0] == u) == (c[w][0] == v))
rotate(v), rotate(u);
else
rotate(u), rotate(u);
Push_up(u);
}
}
void join(int u, int k, int val) {
int d = k >= Rank[u];
c[u][d] = Newnode(val, k); fa[n] = u;
int t = n;
while(t) {
Push_up(t);
t = fa[t];
}
Splay(n, 0);
}
void insert(int k, int val, int u) {
int d = k >= Rank[u];
if(c[u][d])
insert(k, val, c[u][d]);
else join(u, k, val);
}
void update(int k, int val, int u) {
if(Rank[u] == k) {
Val[u] = val;
Push_up(u);
return;
}
int d = k >= Rank[u];
if(c[u][d])
update(k, val, c[u][d]);
Push_up(u);
}
int query(int x, int y) {
Splay(tid[x-1], 0);
Splay(tid[y+1], root);
return Max[c[tid[y+1]][0]];
}
}SPT[maxn], test;
char s[20];
int n, m;
int x, y, z, x1, y1, x2, y2;
int main() {
#ifndef ONLINE_JUDGE
freopen("yolk.in", "r", stdin);
freopen("yolk.out", "w", stdout);
#endif
/*test.init();
test.root = test.Newnode(-INF, 0);
test.insert(1, 999, test.root);
test.insert(2, 0, test.root);
test.insert(3, -5, test.root);
test.insert(4, -INF, test.root);
cout << test.query(1, 3) << endl;*/
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) {
SPT[i].init();
SPT[i].root = SPT[i].Newnode(-INF, 0);
for(int j=1; j<=n; j++)
SPT[i].insert(j, 0, SPT[i].root);
SPT[i].insert(n+1, -INF, SPT[i].root);
}
while(m--) {
scanf("%s", s);
if(s[0] == 'C') {
scanf("%d%d%d", &x, &y, &z);
SPT[x].update(y, z, SPT[x].root);
}else {
int ans = 0;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
for(int i=x1; i<=x2; i++) ans = max(ans, SPT[i].query(y1, y2));
cout << ans << endl;
}
}
return 0;
}