zoukankan      html  css  js  c++  java
  • TOJ5705动态序列操作(STL or treap)

    传送门:动态序列操作

    在一个动态变化的序列中,完成以下基本操作:

    (1)插入一个整数

    (2)删除一个整数

    (3)查找序列中最大的数

    (4)查找序列中最小的数

    (5)求x的前驱(前驱定义为不大于x的序列中最大的数)

    (6)求x的后继(后继定义为不小于x的序列中最小的数)

    输入

    第一行为n,表示操作的次数,接下来有n行(n≤100000)

    每行为以下操作之一:

    (1)1 x:将x插入

    (2)2 x:删除x,x在序列中一定存在,若有多个相同值,只删除一个。

    (3)3:查找序列中最大的数

    (4)4:查找序列中最小的数

    (5)5 x:求x的前驱

    (6)6 x:求x的后继

    数据保证结果一定存在,其中序列中整数的绝对值不超过107

    输出

    对于op取3、4、5、6等操作,输出相应的结果。

    样例输入

    10
    1 2
    3
    1 5
    4
    1 10
    2 5
    1 3
    6 8
    1 11
    5 3

    样例输出

    2
    2
    10
    3

     

    思路:

    瞎搞:STL vector or 树状数组二分

    正解:treap or splay(我也不会)

    说说vector瞎搞吧,刚开始用set维护,需要另外有一个Map存是否删完了,于是光荣超内存了。扔了几天回头拿vector写了一发过了。

    主要操作只有 insert:插入  earse:删除 , upper_bound  ,lower_bound 两个对vector的二分查找。

    lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址

    upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址

    这里只需要注意,“不大于”,“不小于”这几个字眼即可。

    代码:

    #include<bits/stdc++.h> 
    using namespace std;
    #define LL long long
    #define INF 2000000000
    #define eps 1e-8
    #define pi  3.141592653589793
    vector<int>v;
    int main()
    {
        int _;
        for(scanf("%d",&_);_--;){
            int cmd,x;
            scanf("%d",&cmd);
            if(cmd == 1){
                scanf("%d",&x);
                v.insert(lower_bound(v.begin(),v.end(),x),x);
            }else if(cmd == 2){
                scanf("%d",&x);
                v.erase(lower_bound(v.begin(),v.end(),x));
            }else if(cmd == 3){
                printf("%d
    ",v[v.size()-1]);
            }else if(cmd == 4){
                printf("%d
    ",v[0]);
            }else if(cmd == 5){
                scanf("%d",&x);
                vector<int>::iterator it = lower_bound(v.begin(),v.end(),x);
                if((*it) == x)
                    printf("%d
    ",x);
                else
                    printf("%d
    ",*(--it));
            }
            else if(cmd == 6){
                scanf("%d",&x);
                vector<int>::iterator it = upper_bound(v.begin(),v.end(),x);
                vector<int>::iterator itt = it;
                if(*(--itt) == x && itt!=v.begin())
                    printf("%d
    ",x);
                else
                    printf("%d
    ",*it);
            }
            /*---test---*/
            int f = 0;
            if(f == 1){
                printf("zz :");
                for(int i = 0 ; i < v.size() ; i ++)
                    printf("%d ",v[i]);
                puts("");
            }
            /*---test---*/
        }
        return 0;
    }/*
    10
    1 2
    3
    1 5
    4
    1 10
    2 5
    1 3
    6 8
    1 11
    5 3
    
    
    144
    1 1
    2 1
    1 1
    1 3
    2 3
    1 3
    1 10
    2 10
    1 10
    1 10
    1 11
    6 10
    6 10
    5 10
    6 9
    6 -100
    5 123123
    */

    600MS暴力做法

    如果学完树状数组上二分,会更新一下树状数组二分的求解。

  • 相关阅读:
    FZU Monthly-201906 tutorial
    FZU Monthly-201906 获奖名单
    FZU Monthly-201905 tutorial
    BZOJ1009 GT考试
    BZOJ2428 均分数据
    模拟退火
    BZOJ3680 吊打XXX
    BZOJ4818 序列计数
    BZOJ4103 异或运算
    BZOJ3512 DZY Loves Math IV
  • 原文地址:https://www.cnblogs.com/Esquecer/p/10854146.html
Copyright © 2011-2022 走看看