题意:
给定一个空集合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