Codeforces Round #703 (Div. 2) D. Max Median(二分+前缀和)

题意:

给出一个长度为n的数组,要求找到一段区间,满足长度大于等于k,且中位数最大。

题解:

先考虑二分,我们可以先二分中位数 m i d mid mid,然后再去看能否找到一个区间使其满足要求。接下来的处理比较巧妙:

我们把 ≥ \geq mid的数记为1,反之记为-1,那么可以发现,如果某段区间和为正数,说明 m i d mid mid满足要求。既然要求区间和,那么必然要求前缀和,记 s u m [ i ] sum[i] sum[i]为前缀和,假如以 i i i 为区间结尾存在区间满足要求,那么就是要区间最大值 > 0 >0 >0

即: max ⁡ j = 0 i − k ( s u m [ i ] − s u m [ j ] ) > 0 \max\limits_{j=0}^{i-k}(sum[i]-sum[j]) >0 j=0maxik(sum[i]sum[j])>0,因为 s u m [ i ] sum[i] sum[i]不变,那么要求最大值,只要求 s u m [ j ] sum[j] sum[j]的最小值即可,设 d p [ i ] dp[i] dp[i]为前缀和的前缀最小值,那问题就转化为判断 s u m [ i ] − d p [ i − k ] sum[i]-dp[i-k] sum[i]dp[ik]是否 > 0 >0 >0

代码:

#include<bits/stdc++.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=2e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int a[MAXN];
int dp[MAXN];
int n,k;
int sum[MAXN];
bool check(int mid)
{
    
    
    for(int i=1;i<=n;i++) dp[i]=1e9;
    for(int i=1;i<=n;i++)
    {
    
    
        if(a[i]>=mid) sum[i]=sum[i-1]+1;
        else sum[i]=sum[i-1]-1;
        dp[i]=min(dp[i-1],sum[i]);
    }
    for(int i=k;i<=n;i++)
    {
    
    
        if(sum[i]-dp[i-k]>0) return true;
    }
    return false;
}
int main()
{
    
    
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    int l=1,r=n;
    int ans;
    while(l<=r)
    {
    
    
        int mid=(l+r)>>1;
        if(check(mid))
        {
    
    
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/113926668