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\n",v[v.size()-1]);
        }else if(cmd == 4){
            printf("%d\n",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\n",x);
            else
                printf("%d\n",*(--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\n",x);
            else
                printf("%d\n",*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暴力做法

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

posted on 2019-05-12 22:52  Esquecer  阅读(178)  评论(0编辑  收藏  举报

导航