Codeforces1005 E2. Median on Segments (General Case Edition)(二分思想,好题,cf2400)

题意:

在这里插入图片描述

解法:
直接求中位数=m的方案数不好求
问题可以转换为中位数>=m的方案数-中位数>=m+1的方案数
感觉和一些数位dp求[l,r]内方案数的想法有异曲同工之妙.

如何计算中位数>=mid的方案数:
令b[i]=(a[i]>=mid)?1:-1
中位数>=mid的区间, 一定满足区间和>0
那么问题可以转换为有多少个子区间,满足区间和>0

即sum[i]-sum[l]>0, sum[i]>sum[l].
对于每个i,计算满足条件的l的数量即可.

可以用前缀和+树状数组解决.
这题由于数值是+-1,因此前缀和的变化不会超过1,这种情况可以不用树状数组,直接维护有多少个满足条件的l.
Code:
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define int long long
#define PI pair<int, int>
const int maxm=2e6+5;
// const int mod=998244353;
const int mod=1e9+7;

int n,m;
int a[maxm];
int b[maxm];
// 中位数>=mid的方案数
int cal(int mid){
  // >=mid为1, 否则为-1
  // 中位数>=mid的区间, 一定满足区间和>0
  // 那么问题可以转换为有多少个子区间,满足区间和>0
  for(int i=1;i<=n;i++){
    if(a[i]>=mid)b[i]=1;
    else b[i]=-1;
  }
  map<int,int>mp;
  int ans=0;
  // 前缀和
  int sum=0;
  // 满足sum[i]-sum[l]>0的l的数量, 其中l<i
  int cnt=0;
  // sum[i]-sum[l]>0, 即sum[i]>sum[l]
  // 可以用树状数组维护每个sum[i]出现次数的前缀和来处理.
  // 但这里由于sum每次只会变化1, 即只会从sum[i]变到sum[i]+1或者sum[i]-1,
  // 相当于只在前缀和数组上移动一位,我们可以直接维护计数的变化.
  for(int i=1;i<=n;i++){
    // 存入sum[i-1]
    mp[sum]++;
    // 更新cnt
    if(b[i]==1){
      cnt+=mp[sum];
      ans+=cnt;
      sum++;
    } else {
      sum--;
      cnt-=mp[sum];
      ans+=cnt;
    }
  }
  return ans;
}
void solve() {
  cin>>n>>m;
  for(int i=1;i<=n;i++){
    cin>>a[i];
  }
  // 直接求中位数=m的方案数不好求
  // 问题可以转换为中位数>=m的方案数-中位数>=m+1的方案数
  // 感觉和一些数位dp求[l,r]内方案数的想法有异曲同工之妙.
  int ans=cal(m)-cal(m+1);
  cout<<ans<<endl;
}
signed main() {
// #define MULTI_CASE
  ios::sync_with_stdio(0);
  cin.tie(0);
#ifndef ONLINE_JUDGE
  freopen("../in.txt", "r", stdin);
  freopen("../out.txt", "w", stdout);
#endif
#ifdef MULTI_CASE
  int T;
  cin >> T;
  while (T--)
#endif
    solve();
  return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值