2021牛客暑假多校训练#4 J.Average

//编译器级优化
// #pragma GCC optimize("O2")
#include <bits/stdc++.h>
// #include <string>
// #include <iostream>
// #include <vector>
// #include <queue>
// #include <stack>
// #include <map>
// #include <time.h>
// #include <cstring>
// #include <cmath>
// #include <set>
// #include <unordered_map>
// #include <algorithm>
// #include <cstdio>
// #include <cassert>
// #include <bitset>
// #include <bits/extc++.h>
//外部包含文件
// #include "D:/program_learning/vs_code/workplace/ACMtemplate/data_structure/SparseTable.hpp"
// #include "D:/program_learning/vs_code/workplace/ACMtemplate/computational_geometry/Convex.hpp"
//类型别名
using namespace std;
// using B_ll = __int128_t;
// using B_ull = __uint128_t;
using f32 = float;
using f64 = double;
using ll = long long;
//排序用
#define htl(v, n) (v),(v)+(n), greater<decltype((v)[1])>()
#define lth(v, n) (v),(v)+(n), less<decltype((v)[1])>()
//宏函数
#define Mt(args...) make_tuple(args)
#define Mp(a, b) make_pair((a), (b))
#define Gt(a, b) std::get<(b)>((a))
#define Add(a, b) accumulate((a), (b), 0)
#define Abs(a)  (((a) > 0) ? (a) : -(a))
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define Ceil(a, b) (((a) + (b) - 1) / (b))
#define Floor(a, b) ((a) / (b))
#define Pow2(x) ((x) * (x))
#define Pow3(x) ((x) * (x) * (x))
//浮点数关系运算
#define isZero(x) ((x)>0?(x):-(x)<eps)
#define equal(x, y) (abs((x)-(y))<eps)
#define lthan(x, y) ((y)-(x)>eps)
#define bthan(x, y) ((x)-(y)>eps)
//简化循环
#define FOR(i, a, b) for(int i = (ll)(a); i <= (ll)(b); i++)
#define rFOR(i, a, b) for(int i = (ll)(a); i >= (ll)(b); i--)
#define gFOR(i, a) for(int i = h[(a)] ; ~i ; i = ne[i])
#define bFOR(i, a, b) for(int i = (a); i <= (b); i <<= 1)
#define jFOR(i, a, b, step) for(int i = (a); i <= (b); i += (step))
#define iFOR(it, begin, end) for(auto it = (begin); it!=(end);it++)
#define aFOR(a, s) for(auto (a) : (s))
//debug用
#define _var(x) cout << #x << " = " << (x) << endl
#define _arr1(a, n) for(ll j = 0 ; j < (n) ; j ++)  cout << (a)[j] << ((j == (n) - 1) ? endl : space)
#define _arr2(a, n, m) for(ll i = 0; i < (n); i ++) _arr1((a)[i] + 1, (m))
#define checktime() cerr << "Time : " << 1000 * ((double)clock()) / (double)CLOCKS_PER_SEC << "ms\n" ; system("pause")
//加快io
#define endl "\n"
#define __faster_io__  std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0);
//操作输出
#define space " "
#define setd(n) fixed << setprecision(n)
//初始化设置
#define case(t,i) ll t;cin >> t;for(ll i=1;i<=t;i++)
#define _set(b, c) memset((b), (c), sizeof(b))
//模板函数
template<typename T>
int read(T& result) { // fast read
    char ch;int w = 1;
    result = 0;
    
    ch = getchar();
    while(ch != '-' && !(ch >= '0' && ch <= '9'))
        ch = getchar();

    if(ch == '-')
        w = -1;

    while(isdigit(ch)){
        result = result * 10 + (ch - '0');
        ch = getchar();
    }

    result *= w;
    return 1;
}
template<typename T>
void write (T x) { // fast output
    string tmp;string tail = (x < 0) ? "-" : "";
    while(x){
        tmp += x % 10 + '0';
        x /= 10;
    }
    tmp += tail;
    reverse(tmp.begin(), tmp.end());
    cout << tmp;
}
template<typename T>
T qpow(T x, T n, const T& mod){
    ll ans = 1;
    while(n){
        if(n & 1)
            ans = ans % mod * x % mod;
        x = x % mod * x % mod;
        n >>= 1;
    }
    return ans;
}
template<typename T>
inline T lowbit(T& x){
    return x&-x;
}
template<typename T>
T m_plus(T a, T b, const T& mod){
    return (a % mod + b % mod) % mod;
}
template<typename T>
T m_minus(T a, T b, const T& mod){
    return ((a % mod - b % mod) % mod + mod) % mod;
}
template<typename T>
T m_mult(T a, T b, const T& mod){
    return a % mod * b % mod;
}
template<typename T>
T Mod(T x, T y)
{
    return (x % y + y) % y;
}
//常数
constexpr f32 fINF32 = 1e30;
constexpr f64 fINF64 = 1e300;
constexpr int INF32 = 0x3f3f3f3f;
constexpr ll INF64 = 0x3f3f3f3f3f3f3f3f;
constexpr f32 _fINF32 = -1e30;
constexpr f64 _fINF64 = -1e300;
constexpr int _INF32 = 0xcfcfcfcf;
constexpr ll _INF64 = 0xcfcfcfcfcfcfcfcf;
constexpr f64 eps = 1e-9;
const f64 pi = acos(-1);
constexpr ll mod = 9 + 7;
constexpr ll Bit = 1 << 20;
constexpr ll N = 1e5 + 5;
/*定义全局变量*/
/*辅助函数*/
ll n, m, x, y;
ll a[N], b[N];
double sum[N]; // 因为平均值是个浮点数,所以原数组每一项减去平均值之后的前缀和数组也是浮点数数组。
bool check(double pos, ll op){
    // 考虑如何判断当前平均值是否满足要求,即判断原数组中是否存在某一段子段的平均值大于等于当前二分到的这个平均值,
    // 那么我们如果给原数组每一项都减去一个当前的平均值,问题又转化成了,判断是否存在一段子段的和大于等于0,即我们对于处理之后的数组找出其中的最大子段和,
    // 如果该子段和大于0,则当前平均值满足要求。求子段最大和朴素是O(n^2)的复杂度,利用决策单调性可以优化至O(n),算法总的时间复杂度为O(NlogN),对于1e5数量级可以满足要求。
    double ans = _fINF64; // 将最大子段和答案设为最小值,负无穷。
    if(op == 0){
        // a序列
        FOR(i, 1, n){
            sum[i] = sum[i - 1] + a[i] - pos; // 构造新前缀和数组
        }
        double mn = fINF64; // 将当前位置之前的最小前缀和初始化为正无穷
        FOR(i, x, n){ // 注意子段长度至少要满足x
            mn = Min(mn, sum[i - x]); // 更新最小前缀和
            ans = Max(ans, sum[i] - mn); // 用当前前缀和减最小前缀和尝试更新答案
        }
        return !lthan(ans, 0.0); // 返回!(ans < eps)
    }
    else{
        // b序列
        FOR(i, 1, m){
            sum[i] = sum[i - 1] + b[i] - pos;
        }
        double mn = fINF64;
        FOR(i, y, m){
            mn = Min(mn, sum[i - y]);
            ans = Max(ans, sum[i] - mn);
        }
        return !lthan(ans, 0.0);
    }
}
void solve(){
    // 首先通过题意,注意到一个较显然的性质,拥有最大平均值的子矩阵,一定是由a序列具有最大平均值的子段和b序列拥有最大平均值的子段生成的
    // 于是问题转化成了,分别求出两个序列拥有相同平均值的子段,然后加起来就是最终答案了。
    cin >> n >> m >> x >> y;
    
    FOR(i, 1, n)    cin >> a[i];
    FOR(i, 1, m)    cin >> b[i]; 
    
    double ans = 0; // 对a序列二分它的平均值
    double l = 0, r = 1e5;
    while(r - l > eps){
        double mid = (l + r) / 2;
        if(check(mid, 0))
            l = mid;
        else
            r = mid;
    }
    ans += l; // 在最终答案中加上二分出来的平均值

    l = 0, r = 1e5; // 对b序列二分它的平均值
    while(r - l > eps){ 
        double mid = (l + r) / 2;
        if(check(mid, 1))
            l = mid;
        else
            r = mid;
    }
    ans += l;

    cout << setd(10) << ans << endl; // 设定输出位数为小数点后十位,输出答案。
}
/*程序入口*/
int main()
{
#ifdef  LOCAL
    freopen("D:/program_learning/vs_code/workplace/ACMtemplate/DataIn.txt", "r", stdin);
    freopen("D:/program_learning/vs_code/workplace/ACMtemplate/DataOut.txt", "w", stdout);
#endif
	
    __faster_io__

    // case(t, i){
        solve();
    // }

#ifdef  LOCAL
    cout.flush();
    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);
#endif


    checktime();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值