题目
Description
农夫约翰把他的N(1<=N<=1e5)奶牛排在一排来衡量他们的高度,牛i有:高度H_I(1<=H_I<=1e9)纳米–因为FJ认为他需要精确测量!他想选择一些连续的奶牛拍一张照片发给牛摄影大赛。大赛有一个很奇怪的规则,对所有提交的照片:照片有效当且仅当,它描绘了一群中位身高至少大于一定的阈值X(1<=x<=1e9)的奶牛。中位身高定义为:有n头奶牛按从小到大顺序排好,第[(1+n)/2](取上限)头奶牛的身高。例如{7,3,2,6}的中位数是6,和{5,4,8}的中位数是5。FJ想知道他有多少种选择。
Input
*第1行:两个用空格隔开的整数:N和X
*第2 .. N 1:第i行1包含单个整数H_I。
Output
*第1行:选择的个数,注意,该数可能超出32位整数的存储范围。
Sample Input
4 6 10 5 6 2
Sample Output
7
Hint
有10个可能选择。其中,只有7 个的中位数大于6。它们是{10},{6},{10,5},{5,6},{6,2},{10, 5,6},{1
0,5,6,2}
思路
如果不知道怎么求a前面小于a的个数
https://www.cnblogs.com/wzx-RS-STHN/p/13193271.html
首先令小于X的数为-1,大于X的数为1;
再定义一个s[i]前缀和数组表示1-i中-1和1的和;
如果s[i]==0,那么说明1-i中大于X的数和小于X的数 ,他们的数量都是一样的;
如果s[i]>0,那么说明1-i中大于X的数比小于X的数 要大;
也说明1-i中的中位数是大于X的;
举个栗子:
4 6
1 2 8 6
s[1]=-1,s[2]=-2,s[3]=-1,s[4]=0;
s[4]>=0,所以1-4中的中位数6,是大于X的;
所以我们只需要求出每个s[j]-s[i]是否大于等于0就好了;
for(ll i=1;i<=n;i++) for(ll j=i;j<=n;j++) if(s[j]-s[i]>=0) ans++;
这段代码可以转化为求比s[j]小的s[i]有多少个;
这样很明显就可以用树状数组优化了
for(ll i=1;i<=n;i++) { ll x=findout(s[i]);//查找比s[i]并且在s[i]前面的数有多少个 ans+=x; insert(s[i],1);//插入s[i]; }
需要注意的问题是要s[1]=0,因为s[i]-s[1]相当于1-i的前缀和;
如果s[1]不从0开始,那么会少统计1-i的前缀和;
知道这些还不够,你还是不能AC
那么还要注意什么问题呢;
我们加入树状数组的s[i]可能为0或负数,然鹅树状数组是不能出现0或负数的;
所以每次加入的s[i]要加上一个N;
代码
#include<bits/stdc++.h> typedef long long ll; using namespace std; inline ll read() { ll a=0,ha=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') ha=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*ha; } ll n,m,sum[1000010]; ll a1[1000010],s[1000010]; struct oh { ll v,num; }a[1000010]; inline ll lowbit(ll x) { return x&(-x); } inline void insert(ll x,ll y) { while(x<=2*n)// 注意!!!注意!!!!! { sum[x]+=y; x+=lowbit(x); } } inline ll findout(ll x) { ll ans=0; while(x) { ans+=sum[x]; x-=lowbit(x); } return ans; } int main() {//具体请看上面的思路 n=read();m=read(); for(ll i=1;i<=n;i++) { ll x=read(); if(x>=m) a1[i]=1; else a1[i]=-1; } for(ll i=1;i<=n;i++) s[i]=s[i-1]+a1[i];//把前缀和统计出来 insert(n,1); ll ans=0; for(ll i=1;i<=n;i++) {//我们加入树状数组的s[i]可能为0或负数,然鹅树状数组是不能出现0或负数的; //所以每次加入的s[i]要加上一个N; ll x=findout(s[i]+n);//查找比s[i]并且在s[i]前面的数有多少个 ans+=x; insert(s[i]+n,1);//插入s[i]; } printf("%lld ",ans); }