1045 快速排序 (25分)
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 N 个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?
例如给定 , 排列是1、3、2、4、5。则:
1 的左边没有元素,右边的元素都比它大,所以它可能是主元; 尽管 3 的左边元素都比它小,但其右边的 2 比它小,所以它不能是主元; 尽管 2 的右边元素都比它大,但其左边的 3 比它大,所以它不能是主元; 类似原因,4 和 5 都可能是主元。
因此,有 3 个元素可能是主元。
输入格式:
输入在第 1 行中给出一个正整数 N(≤105); 第 2 行是空格分隔的 N 个不同的正整数,每个数不超过 109。
输出格式:
在第 1 行中输出有可能是主元的元素个数;在第 2 行中按递增顺序输出这些元素,其间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
5 1 3 2 4 5
输出样例:
3 1 4 5
题解:
这里的话的,是在没想出什么很好的办法,做完以后去网上看了看正确答案,嗯,打死我我也想不到主元位置跟排序后的位置相同的,这里的话就是比较硬核的用了两个个优先队列来暴力解决了这个问题。
1.我们遍历每一个数的时候,对于左边的数,我们只需要考虑他的最大的值,也就是说最大值在从左向右的过程中,最大值只增不减,所以我们使用一个变量imax来记录左边的最大值。
2.那么对于右边的数来说,就是比较难以处理的情况了。我们这里建立一个小根堆,只要他最小的数没有经过,那么我们就可以一直用右边最小的数字来跟他进行比较。
但是问题来了,最小值万一被取走了呢?
我们是不可以仅仅把这个最小值pop掉的,
拿一段例子来说 假如你即将要遍历的序列是 xxxxx 3 4 2 xxxxx
经过3和4,你没有做出任何操作,只是单纯比较2,然后把2丢出队列,那么次小的数就是3了,但是与前面冲突,因为3已经不在 2的右边了。
所以你就需要另外一个队列,来暂存已经丢弃掉的数了,然后每次要比较的时候处理一下上述情况即可。
/*Keep on going Never give up*/ #pragma GCC optimize(3,"Ofast","inline") #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <math.h> #include <string> #include <list> #include <set> #include <map> #include <queue> #include <stack> #include <algorithm> #include <stdlib.h> #include <vector> #include <cctype> //#define int long long #define endl '\n' using namespace std; const int maxn = 1e5+10; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int inf=0x3f3f3f3f; const ll mod=1e9+7; using namespace std; priority_queue<int,vector<int>,greater<int> >r; priority_queue<int,vector<int>,greater<int> > temp; int a[maxn]; signed main() { int n; cin>>n; for(int i=0;i<n;i++){ scanf("%d",&a[i]); r.push(a[i]); } vector <int> ans; int imax=-1; for(int i=0;i<n;i++){ temp.push(a[i]); while(!temp.empty()&&temp.top()==r.top()){ temp.pop(); r.pop(); } if(imax<a[i]){ if(r.empty()){ ans.push_back(a[i]); } else if(r.top()>a[i]){ ans.push_back(a[i]); } } imax=max(imax,a[i]); } cout<<ans.size()<<endl; if(ans.size()==0) cout<<endl; else for(auto it:ans){ if(it!=ans.back()) printf("%d ",it); else printf("%d\n",it); } return 0; }
主要写一些题目的题解