CF1005E2 题解
发现中位数恰好为 \(m\) 不太好做,考虑进行差分,变为中位数大于等于 \(m\) 的减去大于 \(m\) 的。
以大于等于 \(m\) 举例,大于 \(m\) 同理。若一个子序列中位数大于等于 \(m\),那么这个子序列中大于等于 \(m\) 的数的数量大于小于 \(m\) 的数的数量。于是前缀和算一下大于等于 \(m\) 的数减去小于 \(m\) 的数,看前面的前缀和有多少个小于当前的前缀和即可,可以树状数组维护。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+5;
int n,m,a[N],t[N],ans=0;
int lowbit(int x) {return x&(-x);}
void add(int x) {while(x<=2*n+1) t[x]++,x+=lowbit(x);}
int query(int x) {int ans=0;while(x) ans+=t[x],x-=lowbit(x);return ans;}
signed main() {
	cin>>n>>m;
	for(int i=1; i<=n; i++) cin>>a[i];
	int sum=0;
	add(n+1);
	for(int i=1; i<=n; i++) {
		if(a[i]>=m) sum++;
		else sum--;
		ans+=query(sum+n);
		add(sum+n+1);
	}
	memset(t,0,sizeof(t)),sum=0;
	add(n+1);
	for(int i=1; i<=n; i++) {
		if(a[i]>m) sum++;
		else sum--;
		ans-=query(sum+n);
		add(sum+n+1);
	}
	cout<<ans;
	return 0;
}
最重要的是想到差分。

                
            
        
浙公网安备 33010602011771号