zoukankan      html  css  js  c++  java
  • 【BZOJ3316】JC loves Mkk(分数规划+单调队列)

    点此看题面

    大致题意: 给定一个圆环,你可以选择连续(Lsim R)个数(个数必须为偶数),求最大的平均值。

    分数规划

    这种平均值的问题一看就是分数规划

    考虑我们二分一个答案(x),设我们选择的数是(a_{1sim t})则需要满足:

    [frac{sum_{i=1}^ta_i}tge xLeftrightarrowsum_{i=1}^t(a_i-x)ge 0 ]

    也就是说,给所有数减去(x)之后,就是要求是否存在一个长度为偶数且在(L sim R)范围内的区间使得这段区间内数的总和大于等于(0)

    单调队列

    感觉没什么好说的吧。

    单调队列维护前缀和的最小值即可。

    唯一要注意的就是因为长度必须是偶数,要开两个单调队列。

    关于答案

    我们发现,二分出的答案是小数,而题目要求分数。

    实际上,我们只要记录下得出答案时的长度,然后以答案乘长度为分子,长度为分母,约分一下就可以了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 200000
    #define DB long double
    #define eps 1e-8
    using namespace std;
    int n,k,Mn,Mx,a[N+5],q[2][N+5];DB s[N+5];
    I long long gcd(Con long long& x,Con long long& y) {return y?gcd(y,x%y):x;}
    I bool Check(Con DB& x)//验证答案
    {
    	RI i,op,H[2]={1,1},T[2]={0,0};
    	for(i=1;i^Mn;++i) s[i]=s[i-1]+a[i]-x;for(;i<=n;++i)//计算前部分的前缀和
    	{
    		op=i&1,H[op]<=T[op]&&q[op][H[op]]==i-Mx&&++H[op];//弹出不合法元素
    		W(H[op]<=T[op]&&s[q[op][T[op]]]>=s[i-Mn]) --T[op];q[op][++T[op]]=i-Mn;//加入新元素
    		if((s[i]=s[i-1]+a[i]-x)-s[q[op][H[op]]]>=-eps) return k=i-q[op][H[op]],1;//如果符合条件直接return 1
    	}return 0;
    }
    int main()
    {
    	RI i;scanf("%d%d%d",&n,&Mn,&Mx),Mn&1&&++Mn,Mx&1&&--Mx;
    	for(i=1;i<=n;++i) scanf("%d",a+i),a[n+i]=a[i];n<<=1;//圆环,所以复制一遍
    	DB l=0,r=1e9,mid;W(r-l>eps) Check(mid=(l+r)/2)?l=mid:r=mid;//分数规划
    	Check(l);long long s=l*k+0.5,g=gcd(s,k);
    	return g^k?printf("%lld/%d",s/g,k/g):printf("%d",s/g),0;//输出分数
    }
    
  • 相关阅读:
    PHP分页类
    phpexcel 控制导出数据内容和行数
    phpexcel 导入 和 导出
    PHP无限极分类
    php 对查询结果集进行排序
    php 删除文件夹及文件夹内文件函数
    php 字符串截取函数
    php 获取用户登录的ip
    js layer页面层加载新网站
    分享到qq
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3316.html
Copyright © 2011-2022 走看看