先上一波链接 https://www.luogu.com.cn/problem/P1168

这道题我们有两种写法

第一种呢是线段树,我们首先需要将原本的数据离散化,线段树维护的信息就是区间内有多少个数,

每次加入两个数(也就是单点修改),查询的时候就是查找中位数((x+1)/2 )所在的位置

每次走到一个点 判断左子树中数字的个数(y)是不是就大于等于当前所找的数k 如果是 则往左子树继续走

如果左子树的数字个数(y)小于当前所找的数k,那么就将k减去y,再往右子树走,这样一直走下去就可以找到中位数所在的位置

然后再将其位置所对应的离散化前对应的点输出来就可以了 这样的复杂度是O(nlogn)的

贴一手代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
const int M=1e6+;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
struct qwq{int w,id;}s[M];
int n,xs[M],xp,fr[M];
struct node{int l,r,sum;}e[M];
void build(int x,int l,int r){
e[x].l=l; e[x].r=r;
if(l==r) return ;
int mid=(l+r)>>;
build(x<<,l,mid);
build(x<<^,mid+,r);
}
void up(int x){e[x].sum=e[x<<].sum+e[x<<^].sum;}
void ins(int x,int k){
if(e[x].l==e[x].r){
e[x].sum++;
return ;
}
int mid=(e[x].l+e[x].r)>>;
if(k<=mid) ins(x<<,k);
else ins(x<<^,k);
up(x);
}
int find(int x,int S){
if(e[x].l==e[x].r) return e[x].l;
if(e[x<<].sum>=S) return find(x<<,S);
return find(x<<^,S-e[x<<].sum);
}
int cnt=;
int main(){
n=read();
for(int i=;i<=n;i++){
s[i].w=read();
xs[++xp]=s[i].w;
}
sort(xs+,xs++xp);
for(int i=;i<=n;i++){
int now=lower_bound(xs+,xs+xp+,s[i].w)-xs;
s[i].id=now; fr[now]=s[i].w;
}
// for(int i=1;i<=n;i++) printf("%d ",s[i].id); puts("");
// for(int i=1;i<=n;i++) printf("%d ",fr[i]); puts("");
build(,,n);
ins(,s[].id);
for(int i=;i<=n;i+=){
int ans=find(,(i+)/);
printf("%d\n",fr[ans]);
ins(,s[++cnt].id);
ins(,s[++cnt].id);
}
return ;
}

另一种做法就是用multiset维护,我们将迭代器It 始终指向中位数,每次插入两个数

如果两个数都比他大,就将It++,因为此时中位数在当前 It 所在位置的后一位了

同理如果两个数都比他小,就将 It--, 如果一大一小,那么中位数位置不变,这样就圆满解决了问题

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<set>
using namespace std;
const int M=1e6+;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
int n,s[M],ans[M];
multiset<int>S;
multiset<int>::iterator It;
int main(){
//freopen("1.in","r",stdin);
n=read(); for(int i=;i<=n;i++) s[i]=read();
S.insert(s[]);
It=S.lower_bound(s[]);
int cnt=;
for(int i=;i<=(n+)/;i++){
ans[i]=*It;
S.insert(s[++cnt]);
S.insert(s[++cnt]);
if(s[cnt]>=*It&&s[cnt-]>=*It) ++It;
else if(s[cnt]<*It&&s[cnt-]<*It) --It;
printf("%d\n",ans[i]);
}
return ;
}

洛谷P1168 中位数——set/线段树的更多相关文章

  1. 【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)

    Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插 ...

  2. 洛谷题解P4314CPU监控--线段树

    题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...

  3. 洛谷P3372/poj3468(线段树lazy_tag)(询问区间和,支持区间修改)

    洛谷P3372 //线段树 询问区间和,支持区间修改 #include <cstdio> using namespace std; struct treetype { int l,r; l ...

  4. 洛谷P4065 [JXOI2017]颜色(线段树)

    题意 题目链接 Sol 线段树板子题都做不出来,真是越来越菜了.. 根据题目描述,一个合法区间等价于在区间内的颜色没有在区间外出现过. 所以我们可以对于每个右端点,统计最长的左端点在哪里,刚开始以为这 ...

  5. 洛谷P5111 zhtobu3232的线段树

    题意:给定线段树,上面若干个节点坏了,求能表示出多少区间. 区间能被表示出当且仅当拆出来的log个节点都是好的. 解:每个区间在最浅的节点处计算答案. 对于每个节点维护从左边过来能有多少区间,从右边过 ...

  6. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

  7. 题解——洛谷P2781 传教(线段树)

    可以说是数据结构学傻了的典型案例了 昨天跳到这题上 然后思考了一下 噫!好!线段树裸题 然后打完板子,发现\(  n \le 10^9 \) 显然线段树直接做不太行 然后这题又只有普及的难度 然后我就 ...

  8. 洛谷P4198 楼房重建(线段树)

    题意 题目链接 Sol 别问我为什么发两遍 就是为了骗访问量 这个题的线段树做法,,妙的很 首先一个显然的结论:位置\(i\)能被看到当且仅当\(\frac{H_k}{k} < \frac{H_ ...

  9. 2018.08.16 洛谷P1471 方差(线段树)

    传送门 线段树基本操作. 把那个方差的式子拆开可以发现只用维护一个区间平方和和区间和就可以完成所有操作. 同样区间修改也可以简单的操作. 代码: #include<bits/stdc++.h&g ...

随机推荐

  1. 汇编移位: SHL、SHR、SAL、SAR、ROL、ROR、RCL、RCR

    SHL.SHR.SAL.SAR: 移位指令 ;SHL(Shift Left):      逻辑左移 ;SHR(Shift Right):      逻辑右移 ;SAL(Shift Arithmetic ...

  2. SQL语句分类

    SQL Structured Query Language SQL是结构化查询语言,是一种用来操作RDBMS的数据库语言,当前关系型数据库都支持使用SQL语言进行操作,也就是说可以通过 SQL 操作 ...

  3. tmux 操作简版

    操作session: 操作window: 操作pane: 原文

  4. webpack 4.0 报错

    ERROR in multi ./src/entery.js dist/bundle.jsModule not found: Error: Can't resolve 'dist/bundle.js' ...

  5. Object中有哪些公用方法?

    clone()方法 实现对象的浅复制,只有实现了Cloneable接口才能调用该方法. toString()方法 返回该对象的字符串表示. equals()方法: 在Object中与“==”的定义是一 ...

  6. 客户端模拟线程线程池发送100个文件给socket

    1.线程池模拟发送100个线程发送 2.每个线程启动一个socket发送文件 3.线程池最大并发几个

  7. CSP-S2019 停课日记

    前言 不想上文化课,于是就停课了 (雾) \(10.13\) 停课前一天 今天名义上是放假,所以不算停课. 老师和同学们听说我要停课,都十分的不舍.我啥也没说就悄悄溜到一中来了. \(10.14\) ...

  8. CSS3 Animations

    CSS Animations 是CSS的一个模块,它定义了如何用关键帧来随时间推移对CSS属性的值进行动画处理.关键帧动画的行为可以通过指定它们的持续时间,它们的重复次数以及它们如何重复来控制. an ...

  9. 在子组件中触发事件,传值给父组件-vue

    1.通过$emit触发事件 在子组件<x-test>中触发事件: <button @click="toSearchProduct()">搜索</but ...

  10. LeetCode--054--区螺旋矩阵(java)

    给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素. 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ...