首页 > 其他分享 >[ABC107D] Median of Medians 题解

[ABC107D] Median of Medians 题解

时间:2024-06-07 20:00:48浏览次数:23  
标签:int 题解 Medians mid 中位数 100005 序列 ABC107D 逆序

题目大意:一个长度为 $M$ 的序列的中位数为这个序列从小到大排序后第 $\lfloor\frac M 2\rfloor + 1$ 个数,将这个序列的所有子段的中位数放入一个序列中,求这个序列的中位数。

设一个序列 $a$ 的中位数为 $x$,那么 $a$ 中至少会有一半的数大于等于 $x$,并且 $x$ 是 $a$ 中满足这个条件的数中最大的,因此答案满足单调性,考虑二分答案。
同时也不难发现,上述所求答案满足: $i<j$ 并且 $a_i\leq a_j$ 的数对数量大于等于总对数的一半。

运用差分与前缀和思想,对于每一次二分找到的中间位置,将已排列好的原序列的中间位置的值与未排序序列中的元素作比较,如果该值比原序列的中间位置的值小则标记为 $-1$,否则标记为 $1$,同时对标记数组求前缀和。

现在问题转化为了在前缀和数组里求 $i<j$ 并且 $a_i\leq a_j$ 的数对数量是否大于等于总对数的一半,我们发现这种数对的数量等于总对数减去 $i<j$ 并且 $a_i>a_j$ 的数对数量,这不就是逆序对吗?

设序列元素个数为 $n$,运用归并排序思想求出逆序对数量,再判断总对数 $\frac{n(n+1)}{2}$ 减去逆序对数量是否大于总对数数量的一半即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,s[100005],d[100005],f[100005],g[100005];
int ans,sum,num;
int n[100005],m[100005];
void merge(int x,int y){
	if(x==y) return ;
	int mid=(x+y)/2;
	merge(x,mid);
	merge(mid+1,y);
	int i=x,j=mid+1,k=x;
	while(i<=mid&&j<=y){
		if(f[i]<=f[j]){
			m[k++]=f[i++];
		}
		else{
			m[k++]=f[j++];
			sum+=mid-i+1;
		}
	}
	while(i<=mid) m[k++]=f[i++];
	while(j<=y) m[k++]=f[j++];
	for(int i=x;i<=y;i++) f[i]=m[i];
}
bool check(int x){
    for(int i=1;i<=a;i++){
        if(s[i]<g[x]){
            f[i]=f[i-1]-1;
        }
        else {
            f[i]=f[i-1]+1;
        }
    }
    merge(0,a);
    if(num-sum>=num/2){
        return true;
    }
    return false;
}
signed main(){
	scanf("%lld",&a);
    num=a*(a+1)/2;
	for(int i=1;i<=a;i++){
		scanf("%lld",&s[i]);
        g[i]=s[i];
	}
    sort(g+1,g+a+1);
	int l=1,r=a;
	while(l<=r){
		int mid=(l+r)/2;
		if(check(mid)){
			ans=g[mid];
            l=mid+1;
		}
		else{
			r=mid-1;
		}
        sum=0;
	}
    printf("%lld",ans);
	return 0;
}

标签:int,题解,Medians,mid,中位数,100005,序列,ABC107D,逆序
From: https://www.cnblogs.com/PerchLootie/p/18237792

相关文章

  • プログラミングコンテストチャレンジブック 题解
    题目大意:从$n$根木棒里选出六根拼成两个合法的三角形,使这两个三角形的周长和最大。考虑贪心,证明在后面。首先我们要知道一个三角形基本定理:较短两边长度之和大于最长边。那我们就根据这个定理先去寻找最大三角形的最长边。先排序,然后循环枚举,对于每个$a_i$,可以寻找到的最大......
  • [COCI2020-2021#2] Sjekira 题解
    题目大意:把一棵树完全分解,每次分解一条边的代价是这条边连接的两个连通块的最大点权之和,求最小代价。逆序模拟,既然题目要求将树完全分解,那我们就每次逆序连接当前权值最小的两个点,也就是贪心的思路。尝试将贪心的值写成一个表达式:$$\sum_{i=1}^na_i+\sum_{(u,v)\inE}\max(a......
  • [ABC036D] 塗り絵 题解
    题意题面讲挺清楚的就不简化了。思路树上求方案数,很明显是树上dp。设$dp_{i,0/1}$表示第$i$个点涂成白/黑色的方案数。当前结点如果为白色,那么它的子节点涂成什么颜色都没关系,根据分步乘法原理,将它子结点涂成白/黑色的方案数之和乘起来即可;当前结点如果为黑色,那么它的子......
  • [ABC126D] Even Relation 题解
    题意对一棵有$N$个点,$N-1$条边的树进行黑白染色,使得每两个距离为偶数的点颜色都一致。思路首先让我们回顾一下加法的性质:偶$+$偶$=$偶奇$+$奇$=$偶偶$+$奇$=$奇不难看出,距离为偶数的关系是可以传递的,而距离为奇数的关系不行。我们只需要做一遍dfs,对一个......
  • [ABC191E] Come Back Quickly 题解
    题面:给你一个$n$个点$m$条边的有向图,第$i$条边$a_i$,$b_i$,$c_i$,表示一条单向边从$a_i$到$b_i$,长度为$c_i$,可能会有重边和自环。问能否从第$i$号点出发然后回到该点形成一个环?可以则输出最短时间,否则输出$-1$。思路:不难发现本题考查的是最短路。观察题面,发现边数......
  • [ABC126F] XOR Matching 题解
    很好的构造题。题意请构造一个长度为$2^{m+1}$的序列$a$,该序列满足:$\foralli\in[1,2^{m+1}],a_i\in[0,2^m-1]$且每个数都恰好出现两次。对于任意一对$(i,j)$满足$a_i=a_j$,$a_i\oplusa_{i+1}\oplus\cdots\oplusa_{j-1}\oplusa_j=k$。$\oplus$表......
  • 食物链题解
    由题得,所有动物整体关系如上。起初每个动物相互时间没有关系,bb[i]=i。对于x与y:如果它们是同类即x到y的距离为$0$,或者转了几圈,一圈距离为$3$,即模$3$余$0$。如果x捕食y,就是x到y距离模$3$余$1$。对x与y操作时:如果它们没有关系(它们不被之前给出的某......
  • 题解:ABC270G Sequence in mod P
    题目传送门思路题目给出了一个数列\[x_{i+1}\equiv{a\timesx_i+b}\pmod{p}\]并想要求最小的\(x_i=G\),那我们可以考虑求出这个数列的通项公式。具体的,观察到原式可以转化成一个等比数列的形式,所以我们可以先设一个常数\(k\),使得\[x_{i+1}+k=a(x_i+k)\]替换进原先的式子......
  • codeforces round 961题解(A、B、C)
    A.GuesstheMaximum因为\(i<j\),所以所有的\([i,j]\)区间中都至少包含两个相邻元素,所以只要求出所有相邻元素中较大值的最小值即可。intn;inta[N];voidsolve(){cin>>n;intmin_v=1e9+1;for(inti=1;i<=n;i++){cin>>a[i];......
  • 怎么发送超大文件?困扰已久的邮件大附件发送问题解决了!
    邮件是日常中使用最多的文件流转工具,特别是对于企业内部的员工间、及企业与企业间的业务开展,数据和文件的发送、业务留痕大多都基于邮箱展开。邮箱的普遍使用给用户基于邮箱进行业务沟通提供了前提,其中,Outlook邮箱是使用最广泛的邮箱之一。这使得邮箱成为一种最常用的通讯工具,但......