Splay 区间信息的维护与查询 静态模板

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值