codeforces 939E - Maximize (三分 / 双指针)

该博客讨论了一种动态规划结合三分查找的算法,用于解决给定集合中选取子集,使得子集最大值减去元素平均值最大的问题。通过分析问题特性,确定了子集最大值始终为集合最大值,其余元素为连续前缀。博主提供了双指针和三分查找两种解决方案,并解释了算法的思路和每一步操作的原因。通过代码实现,展示了如何在O(n log n)的时间复杂度内求解问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

题意:
给定一个空集合S,操作1是每次加入一个数,保证不会小于当前集合的最大数,操作2是询问,从该集合选出一个子集,满足子集最大值减去元素平均值最大,输出这个最大值。

1<=q<=5e5

首先可以感性地想到选出来的子集的2个性质,

①选出来的最大元素一定是集合S的最大值,即:每次都选最新加入的元素。
②其余的元素是集合S的一个连续的前缀(按升序排列之后) .

为什么呢?
①:在这里插入图片描述

②:如果我们选的是s[1],s[2],s[4],s[5],那么如果我们用s[3]去代替s[4],总和一定会减小,所以被挑出来的元素中,除去最大值外,一定是一个连续前缀。

所以我们就可以双指针了,r指向当前加入的最新元素,代表最大值的位置,l表示最优的前缀位置,使得平均值最小. 当r++,l也右移动寻找到当前最小的位置。

其实这个平均值是以l为变量的下凹函数,也就是说,随着加入的元素越来越多,平均值会先下降再上升。 而r++,只会让极值点右移。

所以我们也可以用三分法求函数峰值。

双指针:

#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define ull unsigned long long
#define ll long long
#define pii pair<int, int>
const int maxn = 5e5 + 10;
const ll mod = 1e9 + 7;
const ll inf = (ll)2e14+5;
const int INF = 1e9 + 7;
const double pi = acos(-1.0);
ll inv(ll b){
   while(b==1)return 1;return(mod-mod/b)*inv(mod%b)%mod;}
inline ll read()
{
   
    ll x=0,f=1;char ch=getchar
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值