zoukankan      html  css  js  c++  java
  • (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

    -

  • 相关阅读:
    Codeforces 1255B Fridge Lockers
    Codeforces 1255A Changing Volume
    Codeforces 1255A Changing Volume
    leetcode 112. 路径总和
    leetcode 129. 求根到叶子节点数字之和
    leetcode 404. 左叶子之和
    leetcode 104. 二叉树的最大深度
    leetcode 235. 二叉搜索树的最近公共祖先
    450. Delete Node in a BST
    树的c++实现--建立一棵树
  • 原文地址:https://www.cnblogs.com/de-compass/p/12145960.html
Copyright © 2011-2022 走看看