zoukankan      html  css  js  c++  java
  • 中位数

    问题
    C得到了一个非常神奇的序列A。这个序列长度为N,下标从1开始。A的一个
    子区间对应一个序列,可以由数对[l,r]表示,代表A[l], A[l + 1], ..., A[r]这段数。
    对于一个序列B[1], B[2], ..., B[k],定义B的中位数如下:

    1. 先对B排序。得到新的序列C。 2. 假如k是奇数,那么中位数为 。假如k为偶数,中位数为 。
      对于A的所有的子区间,N可以知道它们对应的中位数。现在小N想
      知道,所有长度>=Len的子区间中,中位数最大可以是多少。

    解:
    网上找到的题目 觉得很好就记下来了
    首先二分答案的题目满足的性质一定是单调性
    不一定是最小值最大或者最大值最小
    当我们对于答案没有思路的时候不妨逆向思考利用二分答案增加条件
    此题便是如此
    首先直接暴力似乎不可做 并且答案也不好求 这让我想起了CF上的一道题 也是求中位数并且利用了二分答案
    正着不好思考 答案似乎太难求
    假如二分答案的话 似乎大于的都可以标为1 小于的话都可以标为-1 因为数值并不产生影响我们只会关心大小关系 调大mid 显然合法的区间会变小 调大mid合法的区间会变大 满足单调性 我们考虑二分答案
    那一个区间的合法条件是什么呢???
    区间的和>0 代表存在一个序列 使得 中位数>mid 假如我们调大mid 存在性就会越来越小 换句话说我们只要逼近二分的答案 就能出解

    code:

    //
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define maxnn 200100
    ll n,LEN;
    ll a[maxnn];
    ll b[maxnn];
    ll sum[maxnn];
    bool isok(ll mid)
    {
    	ll pos=0,ans=1111111000000;
    	for(int i=1;i<=n;i++)
    	{
    		if(a[i]>=mid) b[i]=1;
    		else b[i]=-1;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		sum[i]=sum[i-1]+b[i];
    		while(pos<=i-LEN)
    		{
    			ans=min(ans,sum[pos]);
    			pos++;
    		}
    		if(i>=LEN)
    		if(sum[i]-ans>0) return true;
    	}
    	return false;
    }
    int main()
    {
    	scanf("%lld%lld",&n,&LEN);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    	}	
    	ll l=0,r=100000000000;
    	while(l<=r)
    	{
    		ll mid=(l+r)/2;
    		if(isok(mid))
    		{
    			l=mid+1;
    		}
    		else
    		{
    			r=mid-1;
    		}
    	}
    	cout<<r;
    }
    
  • 相关阅读:
    【JAVA SE基础篇】28.面向对象三大特征之多态
    【JAVA SE基础篇】27.面向对象三大特征之封装
    【JAVA SE基础篇】26.toString()方法和equlas()方法
    【JAVA SE基础篇】25.面向对象三大特征之继承
    【JAVA SE基础篇】24.包的机制和import详解
    ssh框架文件上传下载
    java格式化时间格式
    表单提交后打印后台传过来的数据
    使用ajaxfileupload.js实现文件上传
    JSTL跳出<c:forEach>循环
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11828047.html
Copyright © 2011-2022 走看看