• CF1486D Max Median


    Description

    给定一个长为 (n) 的序列 (a_i),求最大的区间中位数,且该区间长度大于 (k)

    Solution

    这道题的转换挺巧妙。

    对于一个数 (x),若其大于等于一个区间的中位数,当且仅当大于等于它的数的个数 (>) 小于它的数个数。这两类在序列中重新赋值,大于等于赋为 1,小于的赋为 -1,那么条件成立当且仅当区间和是正数。所以想到二分一个 (x),然后做上述转换,判断存不存在这样的一个区间,那么只需要求出最大子段和。可以前缀和优化,子段和即为 (s_r-s_{l-1}) 。固定右端点 (r),在 ([1,r-k])(s_{l-1}) 最小的即可。

    #include<stdio.h>
    
    const int N=200007;
    
    inline int read(){
    	int x=0,flag=1; char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-') flag=0; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    	return flag? x:-x;
    }
    
    int n,k,a[N],b[N];
    
    inline int min(int x,int y){return x<y? x:y;}
    inline int max(int x,int y){return x>y? x:y;}
    bool check(int x){
    	for(int i=1;i<=n;i++)
    		b[i]=b[i-1]+((a[i]>=x)? 1:-1);
    	int ret=0,s=n;
    	for(int i=k;i<=n;i++){
    		s=min(s,b[i-k]);
    		ret=max(ret,b[i]-s);
    	}
    	return ret>0;
    }
    
    int main(){
    	n=read(),k=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	int l=1,r=n,ans=0;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(check(mid)) l=mid+1,ans=mid;
    		else r=mid-1;
    	}
    	printf("%d",ans);
    }
    
  • 相关阅读:
    Inter IPP 跟 Microsoft V100编译器区别
    目标描述(基于区域的描述)
    目标描述(基于边界的描述)
    目标表达(基于区域的表达)
    表达描述(基于变换的表达)
    目标表达(基于边界的表达)
    分割技术扩展
    分水岭分割算法
    借助均移确定聚类中心
    借助过度区选择阈值
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14415138.html
Copyright © 2020-2023  润新知