题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5249
分析:树状数组纪录元素排序后的下标,然后二分查找中位数。
树状数组+二分实现代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int maxn=10005;
int c[maxn<<2];
int n,a[maxn],b[maxn];
char str[maxn][10];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)
{
while(x<maxn)
{
c[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
int s=0;
while(x>0)
{
s+=c[x];
x-=lowbit(x);
}
return s;
}
int solve(int x)
{
int id,l=1,r=maxn,mid;
id=x/2+1;
while(l<=r)
{
mid=(l+r)>>1;
if(sum(mid)>=id) r=mid-1;
else l=mid+1;
}
return b[l];
}
int main()
{
int T=1,x;
while(scanf("%d",&n)!=-1)
{
queue <int> que;
memset(c,0,sizeof(c));
int cnt=1;
for(int i=1;i<=n;i++)
{
scanf("%s",str[i]);
if(str[i][0]=='i')
{
scanf("%d",&x);
b[cnt++]=x;
a[i]=x;
}
}
sort(b+1,b+1+cnt);
cnt=unique(b+1,b+1+cnt)-(b+1);
printf("Case #%d:\n",T++);
for(int i=1;i<=n;i++)
{
if(str[i][0]=='i')
{
x=lower_bound(b+1,b+1+cnt,a[i])-b;
update(x,1);
que.push(x);
}
if(str[i][0]=='o')
{
x=lower_bound(b+1,b+1+cnt,b[que.front()])-b;
update(x,-1);
que.pop();
}
if(str[i][0]=='q')
printf("%d\n",solve(que.size()));
}
}
return 0;
}
在网上看到有用set容器类直接做的:同时维护left和right两个容器,其中,right容器第一个元素纪录中位数。
实现代码如下:
#include <cstdio>
#include <queue>
#include <set>
using namespace std;
set<int>l, r;
set<int>::iterator it;
queue<int>q;
int main()
{
int cas = 1, n;
while(~scanf("%d", &n))
{
printf("Case #%d:\n", cas++);
while(!q.empty()) q.pop();
l.clear(), r.clear();
while(n--)
{
char str[20];
scanf("%s", str);
if(str[0] == 'i')
{
int a;
scanf("%d", &a);
q.push(a);
if(l.size() == r.size())
{
if(r.size() == 0 || a > *l.rbegin())
r.insert(a);
else
{
r.insert(*l.rbegin());
l.erase(*r.begin());
l.insert(a);
}
}
else
{
if(a > *r.begin()) l.insert(*r.begin()), r.erase(*l.rbegin()), r.insert(a);
else l.insert(a);
}
}
else if(str[0] == 'q') printf("%d\n", *r.begin());
else
{
int a = q.front(); q.pop();
if(a < *r.begin()) l.erase(a);
else r.erase(a);
if(l.size() + 1 < r.size()) l.insert(*r.begin()), r.erase(*l.rbegin());
else if(l.size() > r.size())r.insert(*l.rbegin()), l.erase(*r.begin());
}
}
}
return 0;
}