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号