为了能到远方,脚下的每一步都不能少.|

园龄:粉丝:关注:

2021-08-21 15:58阅读: 69评论: 0推荐: 0

牛客练习赛87

中位数

(考时脑壳抽了

思路其实很简单
容易知道最终序列长度为nk
如果不操作,最小的中位数,即为位置为(nk+1)/2

我们把删去的数全都往中位数右边的数加即可,中位数不变
nk的序列中位数最小值 就是位置(nk+1)/2

如果k==n1,原序列和即为所求

记得排序(

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int t;const int maxn=2e5+10;
int n,k;
int m[maxn];
int main(){
	cin>>t;
	while(t--){
		cin>>n>>k;long long ans=0;
		for(int i=1;i<=n;++i) cin>>m[i],ans+=m[i];
		sort(m+1,m+1+n);
		if(k==n-1) cout<<ans<<endl;
		else cout<<m[(n-k+1)/2]<<endl;
	}return 0;
}

k小数查询

怎么又没读懂题就在那里乱做(我是蒟蒻

给定[1,n]的一个排列

又给定一个数x,找出区间第k小为x

就是看区间[l,r]内,有k个数小于等于x

根据题意,l一定小于x这个数的位置,同理r一定大于x这个数的位置

区间问题,又是静态,则可以考虑前缀和

sum[i]为前i个小于x的数量,那么我们就可以想到用sum来表示满足题意,即sum[r]sum[l1]=k,这个区间内有k个数小于等于x

处理sum[]很好处理,只需要,令小于x的数为1,大于x的数为0,前缀和处理即可

但是根据sum[r]sum[l1]=k,是两个端点都在动,暴力枚举直接TLE,考虑只枚举一个端点,

比如只枚举r,我们稍微移项,sum[l1]=sum[r]k,此时我们所需的即为sum[l-1]也就是sum[r]-k的个数,

所以统计出sum[l1]的数量,而l1[0,pos1],则枚举范围[0,pos1](sum[0]=1因为一定有sum[r]k=0),建一个map统计即可

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
using namespace std;
#define int long long
int n;const int maxn=2e5+10;
int a[maxn];
map<int ,int >mp;
int x,k;
int pos;
int sum[maxn];
signed main(){
	cin>>n>>x>>k;
	for(int i=1;i<=n;++i)	{
		cin>>a[i];
		if(a[i]==x) pos=i;
		if(a[i]<=x) sum[i]=1+sum[i-1];
		else sum[i]=sum[i-1];
	}
	for(int i=1;i<pos;++i) mp[sum[i]]++;
	int ans=0;mp[0]++;
	for(int i=pos;i<=n;++i) ans+=mp[sum[i]-k];
	cout<<ans<<endl;
	return 0;
}

ZFY AK IOI

本文作者:归游

本文链接:https://www.cnblogs.com/guiyou/p/15168466.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   归游  阅读(69)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起