洛谷P3380 二逼平衡树

线段树+平衡树

我!又!被!卡!常!了!

以前的splay偷懒的删除找前驱后继的办法被卡了QAQ

放一个在洛谷开O2才能过的代码。。我太菜了。。

#include <bits/stdc++.h>
#define INF 2147483647
#define rint register int
#define full(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int X = 0, w = 0; char ch = 0;
    while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
static short c[20], top;
inline void print(int x){
    if(!x){ putchar(48); putchar('\n'); return;}
    if(x < 0) putchar('-'),x *= -1;
    for(top = 0; x ; c[++top] = x % 10, x /= 10);
    for(; top; putchar(c[top--]^48));
    putchar('\n');
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}

const int N = 3000005;
int n, m, tot, tmp, root[N], val[N], size[N], fa[N], ch[N][2], cnt[N], a[N];

inline int init(rint v, rint f){
    ++tot;
    val[tot] = v, fa[tot] = f,  size[tot] = cnt[tot] = 1;
    ch[tot][0] = ch[tot][1] = 0;
    return tot;
}

inline void push_up(rint x){
    size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x];
}

inline void rotate(rint x){
    int y = fa[x], z = fa[y], p = (ch[y][1] == x) ^ 1;
    ch[y][p^1] = ch[x][p], fa[ch[x][p]] = y;
    ch[z][ch[z][1] == y] = x, fa[x] = z;
    ch[x][p] = y, fa[y] = x;
    push_up(y), push_up(x);
}

inline void splay(rint i, rint x, rint goal){
    if(x == goal) return;
    while(fa[x] != goal){
        int y = fa[x], z = fa[y];
        if(z != goal){
            (ch[y][0] == x) ^ (ch[z][0] == y) ? rotate(x) : rotate(y);
        }
        rotate(x);
    }
    push_up(x);
    if(goal == 0) root[i] = x;
}

inline void insert(rint i, rint x){
    if(!root[i]){
        root[i] = init(x, 0);
        return;
    }
    rint cur = root[i];
    while(ch[cur][x > val[cur]]){
        if(x == val[cur]) break;
        cur = ch[cur][x > val[cur]];
    }
    if(x == val[cur]) cnt[cur] ++, splay(i, cur, 0);
    else ch[cur][x > val[cur]] = init(x, cur), splay(i, ch[cur][x > val[cur]], 0);
}

inline void find(rint i, rint x){
    if(!root[i]) return;
    rint cur = root[i];
    while(x != val[cur] && ch[cur][x > val[cur]])
        cur = ch[cur][x > val[cur]];
    splay(i, cur, 0);
}

/*inline int precursor(rint i, rint x){
    find(i, x);
    if(val[root[i]] < x) return root[i];
    rint cur = ch[root[i]][0];
    while(ch[cur][1]) cur = ch[cur][1];
    return cur;
}

inline int successor(rint i, rint x){
    find(i, x);
    if(val[root[i]] > x) return root[i];
    rint cur = ch[root[i]][1];
    while(ch[cur][0]) cur = ch[cur][0];
    return cur;
}*/

inline int precursor(int i, int v){
    int x = root[i], ans = -INF;
    while (x){
        if (val[x] < v){
            if (ans < val[x]) ans = val[x];
            x = ch[x][1];
        }
        else x = ch[x][0];
    }
    return ans;
}

inline int successor(int i, int v){
    int x = root[i], ans = INF;
    while (x){
        if (val[x] > v){
            if (ans > val[x]) ans = val[x];
            x = ch[x][0];
        }
        else x = ch[x][1];
    } return ans;
}


inline void remove(rint i, rint x){
    rint pre = precursor(i, x), suc = successor(i, x);
    splay(i, pre, 0), splay(i, suc, root[i]);
    rint key = ch[suc][0];
    if(cnt[key] > 1) cnt[key] --, splay(i, key, 0);
    else ch[suc][0] = 0;
    push_up(suc);
}

inline void clear(int x){
    fa[x] = ch[x][0] = ch[x][1] = size[x] = cnt[x] = val[x] = 0;
}

inline void del(rint i, rint x){
    find(i, x);
    int cur = root[i];
    if(cnt[cur] > 1){
        cnt[cur] --;
        return;
    }
    if(!ch[cur][0]){
        int y = ch[cur][1];
        root[i] = y, fa[y] = 0;
        return;
    }
    if(!ch[cur][1]){
        int y = ch[cur][0];
        root[i] = y, fa[y] = 0;
        return;
    }
    int p = ch[cur][0];
    while(ch[p][1]) p = ch[p][1];
    int oldrt = root[i];
    splay(i, p, 0);
    ch[root[i]][1] = ch[oldrt][1];
    fa[ch[oldrt][1]] = root[i];
    clear(oldrt);
    push_up(root[i]);
    return;
}

void buildTree(rint rt, rint l, rint r){
    insert(rt, INF), insert(rt, -INF);
    if(l == r) return;
    rint mid = (l + r) >> 1;
    buildTree(rt << 1, l, mid);
    buildTree(rt << 1 | 1, mid + 1, r);
    push_up(rt);
}

void segInsert(rint rt, rint l, rint r, rint k, rint x){
    insert(rt, x);
    if(l == r) return;
    rint mid = (l + r) >> 1;
    if(k <= mid) segInsert(rt << 1, l, mid, k, x);
    else segInsert(rt << 1 | 1, mid + 1, r, k, x);
}

int segRank(rint rt, rint l, rint r, rint x, rint ql, rint qr){
    if(l == ql && r == qr){
        find(rt, x);
        if(val[root[rt]] >= x) return size[ch[root[rt]][0]] - 1;
        return size[ch[root[rt]][0]] + cnt[root[rt]] - 1;
    }
    rint mid = (l + r) >> 1;
    if(qr <= mid) return segRank(rt << 1, l, mid, x, ql, qr);
    else if(ql > mid) return segRank(rt << 1 | 1, mid + 1, r, x, ql, qr);
    return segRank(rt << 1, l, mid, x, ql, mid) + segRank(rt << 1 | 1, mid + 1, r, x, mid + 1, qr);
}

void segModify(rint rt, rint l, rint r, rint pos, rint k){
    insert(rt, k), del(rt, a[pos]);
    if(l == r) return;
    rint mid = (l +r) >> 1;
    if(pos <= mid) segModify(rt << 1, l, mid, pos, k);
    else segModify(rt << 1 | 1, mid + 1, r, pos, k);
}

int segPrecursor(rint rt, rint l, rint r, rint x, rint ql, rint qr){
    if(l == ql && r == qr){
        return precursor(rt, x);
    }
    rint mid = (l + r) >> 1;
    if(qr <= mid) return segPrecursor(rt << 1, l, mid, x, ql, qr);
    else if(ql > mid) return segPrecursor(rt << 1 | 1, mid + 1, r, x, ql, qr);
    return max(segPrecursor(rt << 1, l, mid, x, ql, mid), segPrecursor(rt << 1 | 1, mid + 1, r, x, mid + 1, qr));
}

int segSuccessor(rint rt, rint l, rint r, rint x, rint ql, rint qr){
    if(l == ql && r == qr){
        return successor(rt, x);
    }
    rint mid = (l + r) >> 1;
    if(qr <= mid) return segSuccessor(rt << 1, l, mid, x, ql, qr);
    else if(ql > mid) return segSuccessor(rt << 1 | 1, mid + 1, r, x, ql, qr);
    return min(segSuccessor(rt << 1, l, mid, x, ql, mid), segSuccessor(rt << 1 | 1, mid + 1, r, x, mid + 1, qr));
}

inline int select(rint l, rint r, rint k){
    rint ll = 0, rr = tmp;
    while(ll < rr){
        rint mid = (ll + rr + 1) >> 1;
        if(segRank(1, 1, n, mid, l, r) + 1 > k) rr = mid - 1;
        else ll = mid;
    }
    return ll;
}

int main(){

    //freopen("data.txt","r",stdin);

    //clock_t startTime = clock();

    n = read(), m = read();
    tmp = -INF;
    buildTree(1, 1, n);
    for(rint i = 1; i <= n; i ++) a[i] = read(), tmp = max(tmp, a[i]), segInsert(1, 1, n, i, a[i]);
    while(m --){
        rint opt = read();
        if(opt == 1){
            rint l = read(), r = read(), k = read();
            print(segRank(1, 1, n, k, l, r) + 1);
            //printf("%d\n", segRank(1, 1, n, k, l, r) + 1);
        }
        else if(opt == 2){
            rint l = read(), r = read(), k = read();
            print(select(l, r, k));
            //printf("%d\n", select(l, r, k));
        }
        else if(opt == 3){
            rint pos = read(), k = read();
            segModify(1, 1, n, pos, k);
            a[pos] = k;
        }
        else if(opt == 4){
            rint l = read(), r = read(), k = read();
            print(segPrecursor(1, 1, n, k, l, r));
            //printf("%d\n", segPrecursor(1, 1, n, k, l, r));
        }
        else if(opt == 5){
            rint l = read(), r = read(), k = read();
            print(segSuccessor(1, 1, n, k, l, r));
            //printf("%d\n", segSuccessor(1, 1, n, k, l, r));
        }
    }

    //clock_t endTime = clock();

    //cout << "time: " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/onionQAQ/p/10770566.html
今日推荐