标签:turn 时间 stdout clu 位置 查找 ble return 二分
? 对于给定序列,求出前奇数个元素的中位数。
? 既然要求中位数,根据题目一看,有点类似与滑动窗口那道题,但想了想,不一样。暴力维护队列,O($n^2$)的时间复杂度面对十万肯定会爆,再试试之前学过的STL模板的优先队列和set是否可以,发现两者对于中位数的查找似乎显得力不从心,想到的只剩下二分了。
? 我们学过插入排序来维护序列,当一个元素加入序列时,将其插入它的理想位置,就像平时斗地主搓麻将理牌一样,可以有效的动态维护有序序列,二分优化后的时间复杂度为O($nlog_2(n)$)能够满足n=100000的要求。
? 我们需要一个既可以高效率实现插入又可以高效率访问中间元素的容器来存储序列,这种既满足链表,又满足数组的特征的容器是什么?vector!(学前误认一无是处,学后方知相见恨晚)
#include <bits/stdc++.h>
using namespace std;
int n;
vector<int> a;
inline int place(int l,int r,int v){
if(l>r)return l;
if(l==r){
return l;
}
if(a[l]==v)return l;
int mid=(l+r)/2;
if(v<a[mid]){
return place(l,mid-1,v);
}
if(v==a[mid]){
return mid;
}
if(v>a[mid]){
return place(mid+1,r,v);
}
}
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d",&n);
a.push_back(-1);
for(register int i=1;i<=n;i++){
int x;
scanf("%d",&x);
int ne=place(0,i-1,x);
while(x<=a[ne-1]&&ne>=1)ne--;//a[ne]<x
while(a[ne]<x&&ne<a.size())ne++;
//cout<<ne<<endl;
vector<int>::iterator it=a.begin()+ne;//a[*it]<=x<a[*it+1]
//while(a[*it]>x)it++;
a.insert(it,x);
//for(int j=0;j<a.size();j++)cout<<a[j]<<‘ ‘;
//cout<<endl;
if(i%2==1){
printf("%d\n",a[(i+1)/2]);
}
}
return 0;
}
? 注:程序本身是考场上胡乱打出的非完全体,所以bug比较多,代码中可以看出加了许多“补丁”。还有,注意不要用cin,cout,会超时等等,还有很多小细节,可以自行去挖掘。
另外几种可行的思路:lower_bound(),堆,平衡树。
标签:turn 时间 stdout clu 位置 查找 ble return 二分
原文地址:https://www.cnblogs.com/returnG/p/13178978.html