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 #defineeps 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暴力做法
如果學完樹狀數組上二分,會更新一下樹狀數組二分的求解。
TOJ5705動態序列操作(STL or treap)