C++STL(set……)
set
底層實現是用紅黑樹。
set 建立
set<int> s; // 不可重,默認升序 set<int,less> s; // 不可重,升序 set<int,greater> s; // 不可重,降序 multiset<int> s; // 可重集set 也可以重載,利用結構體實現。
重載方式同 priority_queue 。
set 插入及訪問
set<int>::iterator it; s.insert(x); // 插入元素 x s.begin(); // 最前面的迭代器 s.end(); // 最后一個元素之后的迭代器(實則空) s.rbegin(); // 最后一個迭代器 s.rend(); // 最前面的前一個迭代器pair<set<int>::iterator,bool> it=s.insert(x); if(it.second) { 插入成功 } else { 插入失敗 }set 大小
s.size(); //返回容器中元素的數目 s.empty(); //判斷容器是否為空set 的刪除操作
s.clear(); //清除所有元素 s.erase(it); //刪除 it 迭代器所指的元素,返回下一個元素的迭代器。 s.erase(l,r); //刪除區間 [l,r) 的所有元素,返回下一個元素的迭代器。 s.erase(x); //刪除容器中值為 x 的元素。有的時候為了避免刪除一個空的位置,在刪除是可以采用以下操作:
s.erase(s.find(*it));set 的查找操作
s.find(x); //查找 x 元素,返回指向 x 元素的迭代器。 s.count(x); //返回容器中值為 x 的元素個數。對 set 來說,要么是 0,要么是 1。對 multiset 來說,值可能大于 1。 s.lower_bound(x); //返回第一個 >=x 元素的迭代器 s.upper_bound(x); // 返回第一個 >x 元素的迭代器。 s.equal_range(x); //返回容器中與 x 相等的上下限的兩個迭代器。上限是閉區間,下限是開區間,如 [l,r) 。例題
P1081 [NOIP2012 提高組] 開車旅行
用 \(\text{set}\) 維護的部分:
給定數列 \(\{h\}\) (\(h_i\) 互不相同),定義兩點 \(i,j(i<j)\) ,它們間的距離 \(dist(i,j)\) 為 \(abs(h[i]-h[j])\) 。
對于每個 \(i\) ,求出距離 \(i\) 最近、次近的 \(j(j>i)\) (若距離一致,\(h\) 越小的 \(j\) 距離 \(i\) 更近)。
考慮用 set 與 lower_bound 實現。
由于最后的幾個數找不到相應的答案,因此要在 set 中提前加入極大、極小的值。
每次查詢 \(i\) 時,查出比 \(h[i]\) 小的最大編號,再訪問其向前、向后的迭代器即可。
部分代碼 h[0]=inf,h[n+1]=-inf; st.insert((Data){inf,0}),st.insert((Data){inf,0}); st.insert((Data){-inf,n+1}),st.insert((Data){inf,n+1}); for(int i=n;i;i--) {int ga,gb; // ga:max_max gb:max_minst.insert((Data){h[i],i});set<Data>::iterator it=st.lower_bound((Data){h[i],i});it--;int ln=(*it).num,lh=(*it).val;it++,it++;int rn=(*it).num,rh=(*it).val;it--;if(abs(lh-h[i])<=abs(rh-h[i])){gb=ln,it--,it--;if(abs(h[i]-(*it).val)<=abs(rh-h[i])) ga=(*it).num;else ga=rn;}else{gb=rn,it++,it++;if(abs(h[i]-(*it).val)>=abs(lh-h[i])) ga=ln;else ga=(*it).num;}fa[0][i][0]=ga;fa[0][i][1]=gb; }priority_queue
應用——對頂堆
維護
void tosame(int size_l) {while(qmin.size()<siz_l) qmin.push(qmax.top()),qmax.pop();while(qmin.size()>siz_l) qmax.push(qmin.top()),qmin.pop(); }void check() {while(qmin.top()>qmax.top()){qmin.pop(),qmin.push(y);qmax.pop(),qmax.push(x);} }例題
P3644 [APIO2015]八鄰旁之橋
給出 \(2n\) 個點,我們需要挑 \(1\) 個點,使得這 \(2n\) 個點到該點的距離和最小。
先考慮 \(k=1\) 的情況,這其實是一個很經典的結論,最優位置顯然在中位數處(即排序后第 \(N\) 個點和第 \(N+1\) 個點之間的任意一點)取得。
接下來是 \(K=2\) 的情況。此時集合點變成了兩個,畫圖后會發現,對于一條線段 \(AB\) 而言,選擇離這個線段中點較近的集合點結果最優。
考慮將所有線段按 \(s_i+t_i\) 的順序排序,枚舉區域分界點,則分界點左邊的區域前往左側集合點,右邊的區域前往右側集合點,問題變成了 \(K=1\) 的情況。
設集合大小為 \(s\),我們維護一個大根堆,存放前 \(\dfrac{s}{2}\) 小的元素,再維護一個小根堆,存放后 \(\dfrac{s}{2}\) 小的元素,則中位數為兩堆的堆頂(任取其一即可)。
代碼
include
reverse 翻轉
翻轉一個 vector:
reverse(a.begin(),a.end());翻轉一個數組:
reverse(a+1,a+n+1);unique 去重
unique 用于“去除”容器中相鄰的重復元素(將重復的放在容器末尾),并返回去重后的尾地址。
由于去除的是相鄰的元素,一般將容器排好序后去重。
例如:
int a[10]={1,1,2,2,2,3,3,4,5,5}; int ans=unique(a,a+10)-a;則 \(ans\) 的值為 \(5\) 。
vector 去重同理:
int m=unique(a.begin(),a.end())-a.begin();rand_shuffle 隨機打亂
用法同 reverse ,經常在模擬退火與爬山算法中使用。
next_permutation 下一個排列
若存在下一個排列,則返回值為 true ,否則為 false 。
lower_bound/upper_bound 二分
指定部分應該是排好序的!
lower_bound 返回第一個大于等于 \(x\) 的元素的迭代器。
upper_bound 第一個大于 \(x\) 的元素的迭代器。
例如:
查找 int 數組中大于等于 \(x\) 的最小整數下標:
int i=lower_bound(a+1,a+n+1,x)-a;在 vector 中查找小于等于 \(x\) 的最大整數(假設存在):
int i=*--upper_bound(a.begin(),a.end(),x);總結
以上是生活随笔為你收集整理的C++STL(set……)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓手机如何清理机身内存
- 下一篇: 内部设计师揭秘!王者峡谷中竟有隐藏的c+