L3-002 特殊堆栈
AC版
lower_bound()函数 ——它实现了二分查找
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
vector.insert(it,x)
在it之前插入x
v.insert(v.begin(),x)
在开头插入x
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <queue>
#define ll long long
const int maxn=1e5+5;
const int INF=0x3f3f3f;
using namespace std;
vector<int> v,st;
int main()
{
int n;
scanf("%d",&n);
vector<int>::iterator it;
while(n--)
{
string s;
cin>>s;
if(s=="Push")
{
int x;
scanf("%d",&x);
st.push_back(x);
it=lower_bound(v.begin(),v.end(),x);//找到第一个>=x的位置
v.insert(it,x);//在it前面插入,即v是有序的 ,这一点有利于后面lower_bound的二分查找
}else if(s=="Pop")
{
if(!st.size())
printf("Invalid\n");
else
{
it=lower_bound(v.begin(),v.end(),st[st.size()-1]);//在顺序存储的v里找到第一个>=要pop的那个元素删掉
v.erase(it);//在有序的那个容器中删除那个>=当前要pop的数
printf("%d\n",st[st.size()-1]);
st.pop_back();
}
}else if(s=="PeekMedian")
{
if(!st.size())
printf("Invalid\n");
else
{
if(v.size()%2)
printf("%d\n",v[v.size()/2]);//实际下标是v.size()-1
else
printf("%d\n",v[(v.size()-1)/2]);
}
}
}
return 0;
}
树状数组+二分
线段树
未AC版
超时emmm,后来一看 时间限制400ms,输入规模1e5,只要有一重循环的就不行了
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <stdlib.h>
#include <set>
#include <vector>
#include <queue>
#define ll long long
const int maxn=1e5+5;
const int INF=0x3f3f3f;
using namespace std;
int cnt=1;
void pop(int a[])
{
cnt--;
printf("%d\n",a[cnt]);
}
int peekmedian(int a[])
{
int st[maxn];
for(int i=1;i<cnt;i++)
st[i]=a[i];
sort(st+1,st+cnt);//实际只有cnt-1个数
if((cnt-1)%2)
printf("%d\n",st[cnt/2]);
else
printf("%d\n",st[(cnt-1)/2]);
}
int main()
{
int n;
scanf("%d",&n);
int a[maxn];
while(n--)
{
string s;
cin>>s;
if(s=="Pop")
{
if(cnt==1)
printf("Invalid\n");
else
pop(a);
}else if(s=="PeekMedian")
{
if(cnt==1)
printf("Invalid\n");
else
peekmedian(a);
}
else if(s=="Push")
{
int x;
scanf("%d",&x);
a[cnt]=x;
cnt++;
}
}
return 0;
}