题目链接

题意:给n个数,求出所有子区间的中位数,组成另外一个序列,求出它的中位数

这里的中位数的定义是:将当前区间排序后,设区间长度为m,则中位数为第m/2+1个数

做法:二分+前缀和+树状数组维护

极其妙的一个做法。

效率$O(nlognlogA)$这里的A指的是原序列中的最大值

二分一下最后的中位数,然后将原序列中大于当前二分出来的值标为1,小于的标为-1,处理出前缀和。

那么只要一段区间的和大于0,那么这段区间的中位数就一定大于等于当前二分出来的值。

所以问题就变成了,求出当前这个序列的顺序对个数(两个数是顺序对,当且仅当$ai<aj,i<j$),用类似于逆序对的方法求

那么做法就很显然了,用树状数组维护一下,单次check的效率就是$O(nlogn)$

要注意的一个点是,这里的树状数组不能有负数,所以得加个1e5强制转正(因为是下标)

至于check的$true$和$false$,如果最后算出来的顺序对个数大于$n*(n-1)/4$那么就是$true$(一共有$n*(n-1)/2$个区间,然后因为我们要求的中位数在中间,所以要再除一次2)

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define inf 1<<30
#define il inline
#define in1(a) read(a)
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
il void readl(ll &x){
x=;ll f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-f;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
x*=f;
}
il void read(int &x){
x=;int f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-f;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
x*=f;
}
using namespace std;
/*===================Header Template=====================*/
#define N 100010
#define lowbit(x) x&-x
int c[N*];
int n,a[N],s[N*];
void add(int x){
for(int i=x;i<=*N;i+=lowbit(i))c[i]++;
}
ll query(int x){
ll sum=;
for(int i=x;i>;i-=lowbit(i))sum+=c[i];
return sum;
}
bool check(int x){
for(int i=;i<=*N;i++)c[i]=;
s[]=;
for(int i=;i<=n;i++)
s[i]=s[i-]+(a[i]>=x?:-);
ll sum=;
for(int i=;i<=n;i++){
sum+=query(s[i]+N);
add(s[i]+N);
}
return sum>=1ll*n*(n+)/;
}
int main(){
in1(n);
int l=,r=;
for(int i=;i<=n;i++){
in1(a[i]);
r=max(r,a[i]);
}
int ans=;
while(l<=r){
int mid=(l+r)>>;
if(check(mid))l=mid+;
else r=mid-;
}
printf("%d\n",r);
}

[AtCoder ARC101D/ABC107D] Median of Medians的更多相关文章

  1. AtCoder - 4351 Median of Medians(二分+线段树求顺序对)

    D - Median of Medians Time limit : 2sec / Memory limit : 1024MB Score : 700 pointsProblem Statement ...

  2. AtCoder Regular Contest 101 (ARC101) D - Median of Medians 二分答案 树状数组

    原文链接https://www.cnblogs.com/zhouzhendong/p/ARC101D.html 题目传送门 - ARC101D 题意 给定一个序列 A . 定义一个序列 A 的中位数为 ...

  3. AtCoder Regular Contest 101 D - Median of Medians

    二分答案 然后前缀和+树状数组来判断这个答案是否大于等于数 如果我们对于一个查询,如果小于这个数令为1,大于这个数领为-1 将所有前缀和放在树状数组中,就可以查询所有sum_{l} < sum_ ...

  4. ARC 101 D - Median of Medians

    题面在这里! 这种题只能二分答案把qwwq,直接做根本做不了啊... 首先你需要知道如何通过 一个区间<=x的数有多少个 来判断x和这个区间中位数的关系. 很显然当数有至少 [L/2]+1 个( ...

  5. AtCoder4351 Median of Medians 二分, 树状数组

    题目大意 定义一个从小到大的数列的中位数为第 $ \frac{n}{2}+1 $ 项.求一个序列的所有连续子序列的中位数的中位数. $ (n \leqslant 100000)$ 问题分析 由于\(n ...

  6. [ARC101B]Median of Medians

    题目   点这里看题目. 分析   看到中位数,当然会想到二分答案.   考虑检查答案.自然,我们需要找出中位数小于二分值\(k\)的区间的个数.考虑构造一个\(b\): \[b_i=(-1)^{[a ...

  7. 【AtCoder】【DP】【思维】Prefix Median(AGC012)

    模的是这位神犇的代码:Atcoder AGC012F : Prefix Median 题意: 在动态中位数那道题上做了一些改动.给你一个序列a,可以将a重新任意排序,然后对于a序列构造出b序列. 假设 ...

  8. 【AtCoder】ARC101题解

    C - Candles 题解 点燃的一定是连续的一段,枚举左端点即可 代码 #include <bits/stdc++.h> #define enter putchar('\n') #de ...

  9. 【arc101】比赛记录

    这场还好切出了D,rt应该能涨,然而这场的题有点毒瘤,700分的D没多少人切,更别说EF了.(暴打出题人)既然这样,干脆就水一篇博客,做个简单的比赛记录. C - Candles 这题是一道一眼题,花 ...

随机推荐

  1. Unity-反编译由IL生成的DLL文件

        本文由博主SunboyL原创,转载请注明出处:http://www.cnblogs.com/xsln/p/DLL_DeCompilation.html     在Unity实际开发过程中,我们 ...

  2. 查询删除安装rpm -qa | grep -i wrapname

    查询:rpm -qa | grep -i wrapname 删除:sudo rpm -ev wrapname 删除依赖:sudo rpm -ev --nodeps mysql-libs-5.6.60- ...

  3. MYSQL中的CASE WHEN END AS

    SELECT id,`NAME`,province,city, phone, CASE sex WHEN 'M' THEN '男' WHEN 'F' THEN '女'END AS sexFROM `p ...

  4. hover()与toggle()

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. soapUI-property Transfer

    1.1.1  Property Transfer 创建或双击现有的Property-Transfer TestStep将打开以下窗口: 左侧的列表显示了此TestStep中配置的传输,添加和管理所需的 ...

  6. [LeetCode] 292. Nim Game_Easy tag: Math

    You are playing the following Nim Game with your friend: There is a heap of stones on the table, eac ...

  7. iOS UI基础-2.0按钮操作与形变

    按钮状态 1.normal:默认状态 Default 对应的枚举常量:UIControlStateNormal   2.highlighted(高亮状态) 按钮被按下去的时候(未松开) 对应的枚举常量 ...

  8. c/c++的预处理定义 Stringizing Operator (#) Charizing Operator (#@) Token-Pasting Operator (##)

    c/c++的预处理定义:一.Stringizing Operator (#)在c和c++中数字标志符#被赋予了新的意义,即字符串化操作符.其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名 ...

  9. PKU2418_树种统计(map应用||Trie树)

    Description Hardwoods are the botanical group of trees that have broad leaves, produce a fruit or nu ...

  10. uva10905

    /* 很好的字符串 比较方法 很多个字符串 组成的 数字 需要最大 然后 比较 a和b 是 比较a+b 和b+a 的大小 */ #include<cstdio> #include<s ...