• (Updating)区间操作数据结构例题


    Description

    你需要写一种数据结构,来维护一个集合 A(元素可重复),其中需要支持如下操作:

    1. Insert(A,x):向集合 A 中插入一个整数 x。

    2. Delete(A,x):删除集合 A 中值为整数 x 的元素,若有多个相同的数,只删除一个,若 x 不存则忽略。

    3. Max(A):查询集合中最大的元素,若不存在则忽略。

    4. Min(A):查询集合中最小的元素,若不存在则忽略。

    5. Find(A,x):查询整数 x 的元素是否存在,若存在输出Y,否则输出N

    6. Pred(A,x):查询求 x 的前驱(前驱定义为小于 x,且最大的数),若 x 没有前驱,则忽略。

    7. Succ(A,x):查询 x 的后继(后继定义为大于 x,且最小的数),若 x 没有后继,则忽略。

    最开始,集合中已经有 n 个元素。

    Input

    第 1 行包含两个整数 n,m,其中 n 表示最初集合 A 中元素的个数, m 表示对集合维护和查询操作数目。

    第 2 行包含 n 个整数,表示开始集合 A 中的元素 a[1]..a[n] (a[i]109)。

    接下来的 m 行,每行的第一项是操作单词,分别是Insert,Delete,Max,Min,Find,PredSucc等操作,

    若该操作有操作参数,则第二项为一个整数 x,为操作的参数 (0x109)。

    Output

    对应输入中的Max,Min,Find,PredSucc操作,每个操作输出该操作的执行结果,若要忽略这个操作,则该项没有输出。

    Sample Input 1 

    10 22
    8 4 1 6 3 5 9 2 7 6
    Insert 10
    Delete 5
    Min
    Max
    Find 6
    Pred 6
    Succ 8
    Delete 6
    Delete 1
    Insert 0
    Delete 10
    Insert 8
    Delete 3
    Find 3
    Succ 8
    Pred 8
    Max
    Min
    Delete 4
    Delete 9
    Succ 8
    Pred 8

    Sample Output 1

    1
    10
    Y
    4
    9
    N
    9
    7
    9
    0
    7

    Hint

    第 16 组数据:0n5000,m10000。

    第 710 组数据:0n10000,m100000。

    第 1120 组数据:0n200000,m2000000。

    所有数据都是随机数据。


    #include<bits/stdc++.h>
    #define lc tr[p].ch[0]
    #define rc tr[p].ch[1]
    using namespace std;
    const int maxn = 2500005, inf=0x3f3f3f3f;
    
    int read() {
        int o=0, f=1;
        char ch;
        while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
        while(isdigit(ch)) o=o*10+ch-'0', ch=getchar();
        return o*f;
    }
    
    struct Treap{
        int ch[2];
        int val, cnt;
        int siz, rk;
    } tr[maxn];
    
    void up(int p) { tr[p].siz = tr[lc].siz + tr[rc].siz + 1; }
    
    void rotate(int &p, int d) {
        int son = tr[p].ch[d];
        tr[p].ch[d] = tr[son].ch[d^1];
        tr[son].ch[d^1] = p;
        up(p); up(p=son);
    }
    
    int np=0;
    void insert(int &p, int x) {
        if(!p) {
            tr[p=++np] = (Treap){0, 0, x, 1, 1, rand()};
            return;
        }
        tr[p].siz++;
        if(tr[p].val == x) { tr[p].cnt++; return; }
        int d = tr[p].val < x; insert(tr[p].ch[d], x);
        if(tr[p].rk > tr[tr[p].ch[d]].rk) rotate(p, d);
    }
    
    void del(int &p, int x) {
        if(!p) return;
        if(tr[p].val == x) {
            if(tr[p].cnt > 1) {
                tr[p].siz--;
                tr[p].cnt--;
                return;
            }
            if(!lc || !rc) {
                p = lc + rc; // 利用引用更新父节点指向 
                return;
            }
            int d = tr[rc].rk < tr[lc].rk;
            rotate(p, d);
            del(p, x);
        } else {
            int d = tr[p].val < x;
            del(tr[p].ch[d], x);
            up(p);
        }
    }
    
    int find(int p, int x) {
        while(p && tr[p].val != x)
            if(tr[p].val < x) p=rc;
            else p=lc;
        return p;
    }
    
    int Max(int p) {
        while(p && rc) p=rc;
        return p;
    }
    
    int Min(int p) {
        while(p && lc) p=lc;
        return p;
    }
    
    int pred(int p, int x) {
        if(!p) return -inf;
        if(tr[p].val >= x) return pred(lc, x);
        return max(tr[p].val, pred(rc, x));
    }
    
    int suc(int p, int x) {
        if(!p) return inf;
        if(tr[p].val <= x) return suc(rc, x);
        return min(tr[p].val, suc(lc, x));
    }
    
    void prt(int p) {
        if(!p) return;
        prt(lc);
        printf("%d %d %d %d %d
    ", p, tr[p].val, tr[p].cnt, lc, rc);
        prt(rc);
    }
    
    int main() {
        int n=read(), m=read(), rt=0;
        while(n--) insert(rt, read());
        while(m--) {
            char op[10];
            scanf("%s", op);
            if(op[0] == 'I') insert(rt, read());
            else if(op[0] == 'D') del(rt, read());
            else if(op[0] == 'F') puts( find(rt, read())? "Y" : "N");
            else if(op[0] == 'P') {
                int t=pred(rt, read());
                if(t != -inf) printf("%d
    ", t);
            }
            else if(op[0] == 'S') {
                int t=suc(rt, read());
                if(t != inf) printf("%d
    ", t);
            }
            else if(op[1] == 'i') {
                if(rt) printf("%d
    ", tr[Min(rt)].val);
            }
            else {
                if(rt) printf("%d
    ", tr[Max(rt)].val);
            }
        }
        return 0;
    }
    //Treap

    -

  • 相关阅读:
    索引的实现:B+树
    SQL Server 查
    SQL Server 增、删、改、小部分查
    最最最最最基础的SQL Server
    三大范式
    SQLserver数据类型
    第一阶段项目
    2017.10.17一阶段项目心得
    jquery&bootstrap
    国庆小长假结束后的一阶段小测验
  • 原文地址:https://www.cnblogs.com/de-compass/p/12145960.html
Copyright © 2020-2023  润新知