<题目链接>

中位数可以转化为区间第k大问题,当然是选择Treap实现名次树了啊。(笑)

功能十分简单的Treap即能满足需求——只需要插入与查找第大的功能。

插入第i个数时,如果i是奇数,随即询问当前排名第(i+1>>1)的数。

注意是一边插入一边询问,这样可以保留原序列的顺序,而不是所有插入完后再询问。

这样一趟下来,所有数都插入完毕了,询问也处理完毕了。

封装版代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
const int MAXN=100010;
int n;
class Treap
{
public:
Treap(void)
{
rt=cnt=0;
memset(a,0,sizeof a);
memset(s,0,sizeof s);
}
void Insert(int x)
{
_Insert(rt,x);
}
int Xth(int x)
{
return _Xth(rt,x);
}
private:
bool a[MAXN];
int rt,cnt;
struct node
{
int l,r,v,p,size,num;
}s[MAXN];
int Random(void)
{
int x;
while(a[x=rand()%MAXN]);
a[x]=1;
return x;
}
void Update(int i)
{
s[i].size=s[s[i].l].size+s[s[i].r].size+s[i].num;
}
void L_Rotate(int &i)
{
int t=s[i].r;
s[i].r=s[t].l,s[t].l=i;
s[t].size=s[i].size;
Update(i),i=t;
}
void R_Rotate(int &i)
{
int t=s[i].l;
s[i].l=s[t].r,s[t].r=i;
s[t].size=s[i].size;
Update(i),i=t;
}
void _Insert(int &i,int x)
{
if(!i)
{
s[i=++cnt].v=x,s[i].p=Random();
s[i].size=s[i].num=1;
return;
}
++s[i].size;
if(x==s[i].v)
++s[i].num;
else if(x<s[i].v)
{
_Insert(s[i].l,x);
if(s[s[i].l].p>s[i].p)
R_Rotate(i);
}
else
{
_Insert(s[i].r,x);
if(s[s[i].r].p>s[i].p)
L_Rotate(i);
}
}
int _Xth(int i,int x)
{
if(!i)
return 0;
int t;
if(x<=s[s[i].l].size)
return _Xth(s[i].l,x);
else if(x>(t=s[s[i].l].size+s[i].num))
return _Xth(s[i].r,x-t);
else
return s[i].v;
}
}T;
int main(int argc,char *argv[])
{
scanf("%d",&n);
srand((unsigned)time(NULL));
for(int i=1,x;i<=n;++i)
{
scanf("%d",&x);
T.Insert(x);
if(i&1)
printf("%d\n",T.Xth(i+1>>1));
}
return 0;
}

精简版代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
const int MAXN=100010;
bool a[MAXN];
int n,rt,cnt;
struct node
{
int l,r,v,p,size,num;
}s[MAXN];
int Random(void)
{
int x;
while(a[x=rand()%MAXN]);
a[x]=1;
return x;
}
void Update(int i)
{
s[i].size=s[s[i].l].size+s[s[i].r].size+s[i].num;
}
void L_Rotate(int &i)
{
int t=s[i].r;
s[i].r=s[t].l,s[t].l=i;
s[t].size=s[i].size;
Update(i),i=t;
}
void R_Rotate(int &i)
{
int t=s[i].l;
s[i].l=s[t].r,s[t].r=i;
s[t].size=s[i].size;
Update(i),i=t;
}
void Insert(int &i,int x)
{
if(!i)
{
s[i=++cnt].v=x,s[i].p=Random();
s[i].size=s[i].num=1;
return;
}
++s[i].size;
if(x==s[i].v)
++s[i].num;
else if(x<s[i].v)
{
Insert(s[i].l,x);
if(s[s[i].l].p>s[i].p)
R_Rotate(i);
}
else
{
Insert(s[i].r,x);
if(s[s[i].r].p>s[i].p)
L_Rotate(i);
}
}
int Xth(int i,int x)
{
if(!i)
return 0;
int t;
if(x<=s[s[i].l].size)
return Xth(s[i].l,x);
else if(x>(t=s[s[i].l].size+s[i].num))
return Xth(s[i].r,x-t);
else
return s[i].v;
}
int main(int argc,char *argv[])
{
scanf("%d",&n);
srand((unsigned)time(NULL));
for(int i=1,x;i<=n;++i)
{
scanf("%d",&x);
Insert(rt,x);
if(i&1)
printf("%d\n",Xth(rt,i+1>>1));
}
return 0;
}

谢谢阅读。

[Luogu 1168] 中位数的更多相关文章

  1. Luogu P1627 中位数

    Luogu P1627 中位数 先记录目标数的位置,并且把数组映射为: $$a[i]=\begin{cases}-1,a[i]<b\0,a[i]=b\1,a[i]>b\end{cases} ...

  2. [luogu]P1168 中位数[堆]

    [luogu]P1168 中位数 题目描述 给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[3], …, A[2k - 1]的中位数.即前1 ...

  3. LuoGu P1168 中位数

    题目描述 给出一个长度为 $ N $ 的非负整数序列 $ A_i $ ,对于所有 $ 1 ≤ k ≤ (N + 1) / 2 $ ,输出 $ A_1, A_3, -, A_{2k - 1} $ 的中位 ...

  4. luogu P1168 中位数 |树状数组+二分

    题目描述 给出一个长度为NN的非负整数序列A_i,对于所有1 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2,输出A_1, A_3, -, A_2k - 1的中位数.即前1,3,5,-个数的 ...

  5. 【Luogu P1168】【Luogu P1801&UVA 501】中位数&黑匣子(Black Box)——对顶堆相关

    Luogu P1168 Luogu P1801 UVA 501(洛谷Remote Judge) 前置知识:堆.优先队列STL的使用 对顶堆 是一种在线维护第\(k\)小的算法. 其实就是开两个堆,一个 ...

  6. luogu P3031 [USACO11NOV]高于中位数Above the Median (树状数组优化dp)

    链接:https://www.luogu.org/problemnew/show/P3031 题面: 题目描述 Farmer John has lined up his N (1 <= N &l ...

  7. luogu P1627 [CQOI2009]中位数

    传送门 要求有多少个长度为奇数的区间满足某个数为区间中位数 这样的区间,大于中位数的数个数 等于 小于中位数的数个数 用类似于前缀和的方法,设\(X_i\)为\(i\)和数\(b\)形成的区间内,大于 ...

  8. [LUOGU] P3871 [TJOI2010]中位数

    题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将一个序列按照从 ...

  9. [Luogu]中位数

    Description Luogu1168 Solution 一种神奇的做法:开一个大根堆和小根堆,保证大根堆比小根堆多1个元素,且大根堆堆顶元素比小根堆堆顶元素小,那么大根堆堆顶就是中位数.插入的时 ...

随机推荐

  1. 基于范围的for语句

    一.关键点 1. 作用过程 遍历给定序列中的每个元素并对序列中的每个值执行某种操作. 2. 若要修改序列中元素的值,需将类型定义为引用 string s("Hello World!!!&qu ...

  2. 单源最短路——dijkstra算法

    Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 问 ...

  3. “Hello World”团队第一周博客汇总

    时间:2017-10-13——2017-10-19 Scrum会议: 会议要求博客:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/1 ...

  4. Thunder团队第五周 - Scrum会议7

    Scrum会议7 小组名称:Thunder 项目名称:i阅app Scrum Master:苗威 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康 ...

  5. 冲刺ing-1

    冲刺一 1.第一天的工作分配: 姓名 任务分工 吴伟华(队长) 布置团队任务,发表汇总博客及第一次冲刺博客 蔺皓雯 讨论任务分配 杨池宇 讨论任务分配 鲁婧楠 讨论任务分配 曾茜 讨论任务分配 蔡晨旸 ...

  6. 【IdentityServer4文档】- 贡献

    贡献 我们非常乐于接受社区贡献,但您应遵循一些指导原则,以便我们可以很方便的解决这个问题. 如何贡献? 最简单的方法是打开一个问题并开始讨论.然后,我们可以决定如何实现一个特性或一个变更.如果您即将提 ...

  7. 【week2】 累计进度条、psp、饼图

    每周例行报告 本周PSP 类别 任务 开始时间 结束时间 被打断时间 总计工作时间 2016年9月9日 读书 构建之法-5.6章 19:00 20:00 0 60min 2016年9月10日 看博客 ...

  8. Thinkphp5图片、音频和视频文件上传

    首先是同步上传,最为基础的上传的方式,点击表单提交之后跳转那种.如下前端代码 <!DOCTYPE html> <html lang="en"> <he ...

  9. djano modles values+ajax实现无页面刷新更新数据

    做项目的过程中想通过不刷新页面的方式来进行页面数据刷新,开始使用http://www.cnblogs.com/ianduin/p/7761400.html方式将查询结果数据进行序列化.发现可以行,但是 ...

  10. 伟大的淘宝IP库的API接口竟然提示503挂掉了

    1 淘宝IP库惊现503错误 吃完晚饭,大概6点半了,天色已暗,太阳早就落山了.回到宿舍打开博客一看,傻眼了:博客每篇文章的评论者的地理信息全部处于“正在查询中……”的状态.这神马情况,不会是被淘宝封 ...