優先佇列 C++STL——優先佇列
C++STL——優先佇列
一、相關定義
優先佇列容器與佇列一樣,只能從隊尾插入元素,從隊首刪除元素。但是它有一個特性,就是佇列中最大的元素總是位於隊首,所以出隊時,並非按照先進先出的原則進行,而是將當前佇列中最大的元素出隊。這點類似於給佇列裡的元素進行了由大到小的順序排序。元素的比較規則預設按元素值由大到小排序,可以過載“<”操作符來重新定義比較規則。
優先順序佇列可以用向量(vector)或雙向佇列(deque)來實現(注意list container不能用來實現queue,因為list的迭代器不是任意存取iterator,而pop中用到堆排序時是要求randomaccess iterator 的!):
priority_queue<vector<int>, less<int> > pq1; // 使用遞增less<int>函式物件排序
priority_queue<deque<int>, greater<int> > pq2; // 使用遞減greater<int>函式物件排序
其成員函式有“判空(empty)” 、“尺寸(Size)” 、“棧頂元素(top)” 、“壓棧(push)” 、“彈棧(pop)”等。
二、priority_queue
基本操作:
empty() 如果佇列為空,則返回真
pop() 刪除對頂元素,刪除第一個元素
push() 加入一個元素
size() 返回優先佇列中擁有的元素個數
top() 返回優先佇列對頂元素,返回優先佇列中有最高優先順序的元素
在預設的優先佇列中,優先順序高的先出隊。在預設的int型中先出隊的為較大的數。
標頭檔案:
#include <queue>宣告方式:
1、普通方法:
priority_queue<int> q; //通過操作,按照元素從大到小的順序出隊 priority_queue<int,vector<int>, greater<int> > q; //通過操作,按照元素從小到大的順序出隊2、自定義優先順序:
struct cmp { operator bool ()(int x, int y) { return x > y; // x小的優先順序高 //也可以寫成其他方式,如: return p[x] > p[y];表示p[i]小的優先順序高 } }; priority_queue<int, vector<int>, cmp> q; //定義方法 //其中,第二個引數為容器型別。第三個引數為比較函式。3、結構體宣告方式:
#include <iostream> #include<algorithm> #include<math.h> #include<cstring> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; int a[100010]; int main() { ll n,k,sum=0;; priority_queue<int,vector<int>,greater<int> >q; while(~scanf("%lld",&n)) { sum=0; scanf("%lld",&k); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); sum+=a[i]; } for(int i=k+1;i<=n;i++) { if(i%(k+1)!=0) { if(q.top()<a[i]) { q.pop(); q.push(a[i]); } } else { q.push(a[i]); } } while(q.size()!=0) { sum-=q.top(); q.pop(); } printf("%lld\n",sum); } return 0; }
思路2: 這個思路差不多,從後面開始入佇列,如果i%(k+1)==0,找佇列中的最大的刪掉。
#include <iostream> #include<algorithm> #include<math.h> #include<cstring> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; int a[100010]; int main() { ll n,k,sum=0;; priority_queue<int,vector<int>,less<int> >q; while(~scanf("%lld",&n)) { sum=0; scanf("%lld",&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); while(q.size()!=0) { q.pop(); } for(int i=n;i>=1;i--) { q.push(a[i]); if(i%(k+1)==0) { q.pop(); } } while(q.size()!=0) { sum+=q.top(); q.pop(); } printf("%lld\n",sum); } return 0; }
一、相關定義
優先佇列容器與佇列一樣,只能從隊尾插入元素,從隊首刪除元素。但是它有一個特性,就是佇列中最大的元素總是位於隊首,所以出隊時,並非按照先進先出的原則進行,而是將當前佇列中最大的元素出隊。這點類似於給佇列裡的元素進行了由大到小的順序排序。元素的比較規則預設按元素值由大到小排序,可以過載“<”操作符來重新定義比較規則。
優先順序佇列可以用向量(vector)或雙向佇列(deque)來實現(注意list container不能用來實現queue,因為list的迭代器不是任意存取iterator,而pop中用到堆排序時是要求randomaccess iterator 的!):
priority_queue<vector<int>, less<int> > pq1; // 使用遞增less<int>函式物件排序
priority_queue<deque<int>, greater<int> > pq2; // 使用遞減greater<int>函式物件排序
其成員函式有“判空(empty)” 、“尺寸(Size)” 、“棧頂元素(top)” 、“壓棧(push)” 、“彈棧(pop)”等。
二、priority_queue
基本操作:
empty() 如果佇列為空,則返回真
pop() 刪除對頂元素,刪除第一個元素
push() 加入一個元素
size() 返回優先佇列中擁有的元素個數
top() 返回優先佇列對頂元素,返回優先佇列中有最高優先順序的元素
在預設的優先佇列中,優先順序高的先出隊。在預設的int型中先出隊的為較大的數。
標頭檔案:
#include <queue>宣告方式:
1、普通方法:
priority_queue<int> q; //通過操作,按照元素從大到小的順序出隊 priority_queue<int,vector<int>, greater<int> > q; //通過操作,按照元素從小到大的順序出隊2、自定義優先順序:
struct cmp { operator bool ()(int x, int y) { return x > y; // x小的優先順序高 //也可以寫成其他方式,如: return p[x] > p[y];表示p[i]小的優先順序高 } }; priority_queue<int, vector<int>, cmp> q; //定義方法 //其中,第二個引數為容器型別。第三個引數為比較函式。3、結構體宣告方式:
struct node { int x, y; friend bool operator < (node a, node b) { return a.x > b.x; //結構體中,x小的優先順序高 } }; priority_queue<node>q; //定義方法 //在該結構中,y為值, x為優先順序。 //通過自定義operator<操作符來比較元素中的優先順序。 //在過載”<”時,最好不要過載”>”,可能會發生編譯錯誤 題: 6 2 10 3 12 15 12 18 6 1 10 3 12 15 12 18 5 5 1 2 3 4 5 Sample Output 37 25 15 題意: 有6個點,分別是第二行的六個數,代表房間的價格;你每k(第一個樣例中的2)就會有一天可以免費,問怎麼樣能使花的錢最少,必須依次住,不能跳著住。 思路1: 第一個樣例: 前兩天一定要選,所以可以刪除一個,從第k+1天到能刪第二個數中,找一個最大的數放在佇列(不一定刪除,因為可能後面有比他大的數,因為佇列空所以不用替換),之後每一個i%(k+1)!=0的數,都要和佇列中最小的數比較,如果這個數大於佇列中的最小的,就替換掉(其實第一次也一樣,只不過第一次的時候佇列為空),如果i%(k+1)==0,就先把他放進佇列,然後就進入上面的情況中。 程式碼如下:#include <iostream> #include<algorithm> #include<math.h> #include<cstring> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; int a[100010]; int main() { ll n,k,sum=0;; priority_queue<int,vector<int>,greater<int> >q; while(~scanf("%lld",&n)) { sum=0; scanf("%lld",&k); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); sum+=a[i]; } for(int i=k+1;i<=n;i++) { if(i%(k+1)!=0) { if(q.top()<a[i]) { q.pop(); q.push(a[i]); } } else { q.push(a[i]); } } while(q.size()!=0) { sum-=q.top(); q.pop(); } printf("%lld\n",sum); } return 0; }
思路2: 這個思路差不多,從後面開始入佇列,如果i%(k+1)==0,找佇列中的最大的刪掉。
#include <iostream> #include<algorithm> #include<math.h> #include<cstring> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; int a[100010]; int main() { ll n,k,sum=0;; priority_queue<int,vector<int>,less<int> >q; while(~scanf("%lld",&n)) { sum=0; scanf("%lld",&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); while(q.size()!=0) { q.pop(); } for(int i=n;i>=1;i--) { q.push(a[i]); if(i%(k+1)==0) { q.pop(); } } while(q.size()!=0) { sum+=q.top(); q.pop(); } printf("%lld\n",sum); } return 0; }