问题 G: Above the Median------------------思维(套路)+树状数组

53 篇文章 0 订阅
19 篇文章 0 订阅

题目描述

Farmer John has lined up his N (1 <= N <= 100,000) cows in a row to measure their heights; cow i has height H_i (1 <= H_i <= 1,000,000,000) nanometers–FJ believes in precise measurements! He wants to take a picture of some contiguous subsequence of the cows to submit to a bovine photography contest at the county fair.

The fair has a very strange rule about all submitted photos: a photograph is only valid to submit if it depicts a group of cows whose median height is at least a certain threshold X (1 <= X <= 1,000,000,000).

For purposes of this problem, we define the median of an array A[0…K] to be A[ceiling(K/2)] after A is sorted, where ceiling(K/2) gives K/2 rounded up to the nearest integer (or K/2 itself, it K/2 is an integer to begin with). For example the median of {7, 3, 2, 6} is 6, and the median of {5, 4, 8} is 5.

Please help FJ count the number of different contiguous subsequences of his cows that he could potentially submit to the photography contest.

输入

  • Line 1: Two space-separated integers: N and X.
  • Lines 2…N+1: Line i+1 contains the single integer H_i.

输出

  • Line 1: The number of subsequences of FJ’s cows that have median at least X. Note this may not fit into a 32-bit integer.
    样例输入 Copy
    4 6
    10
    5
    6
    2
    样例输出 Copy
    7
    提示
    FJ’s four cows have heights 10, 5, 6, 2. We want to know how many contiguous subsequences have median at least 6.There are 10 possible contiguous subsequences to consider. Of these, only 7
    have median at least 6. They are {10}, {6}, {10, 5}, {5, 6}, {6, 2}, {10,5, 6}, {10, 5, 6, 2}.

题意:
给出一串数字,问中位数大于等于X的连续子串有几个。(这里如果有偶数个数,定义为偏大的那一个而非中间取平均)

解析:
这种题目是一种套路题。
怎么个套路法呢????
我们把>=x的数 置为1 把<x的数置为0 然后求一边前缀和。
问题转化为 sum[r]-sum[l-1]>=0
因为前缀和>=0一定满足这个序列至少有一半的数>=x

我们枚举l-1,即0~n-1 每次求sum[r]>=sum[l-1]的r的个数。可以用树状数组求解

因为前缀和可能存在全是负数(有100000个<x的数),所以把坐标整体加一下

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1000;
typedef long long ll;
int c[N];
int cnt[N];
int a[N];
int res[N];
int n,x;
int change(int x) 
{
	return x+100001;
}
int lowbit(int x)
{
	return x&(-x);
}
int add(int i,int x)
{
	while(i<N)
	{
		c[i]+=x;
		i+=lowbit(i);
	} 
}
int sum(int i)
{
	int sum=0;
	while(i)
	{
		sum+=c[i];
		i-=lowbit(i);
	}
	return sum;
}
int main()
{
	cin>>n>>x;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		res[i]=res[i-1]+ (a[i]>=x ? 1 :-1);
	}
	add(change(0),1);
	cnt[change(0)]++;
	for(int i=1;i<=n;i++)
	{
		add(change(res[i]),1);
		cnt[change(res[i])]++;
	}
	ll ans=0;
	for(int i=0;i<n;i++) //枚举l-1
	{
	//n-i,表示还剩下多少个人,-sum(change(res[i])意思的是,剩下的n-i个人如果有小于change(res[i])的人的话,也要减去 。
	// +cnt[change(res[i]))的意思是,因为树状数组求sum(change(res[i]))会把change(res[i])也算上,所以我们还得加回来

		ll t=n-i-sum(change(res[i]))+cnt[change(res[i])];
		ans+=t;
		add(change(res[i]),-1);
		cnt[change(res[i])]--;
	}
	cout<<ans<<endl;
 } 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值