Codeforces 939E Maximize! 离散 三分

题目传送门↓http://codeforces.com/problemset/problem/939/E

  题意:有一最初为空的不下降序列,有两种操作,一种是在序列里增加一个不小于序列尾的整数,另一种是查询当前序列中的某个子集,其最大值为max,平均值为mean,使得子集的max-mean在当前序列的所有子集中最大,输出这个max-mean。

  思考:

  1.序列最大值是否入选,假设不入选,则此时答案的子集中,最大值为max1,和为sum1,元素个数为k则答案可表示为max1 - sum1 / k;若在此答案的基础上更换序列的最大值,此时最大值假设比max1大d,则答案表达式为  max + d - (sum + d) / k  ,对比原式,变化值 Δ= d - d/k >=0 ,因此对每个子集,必定包含序列的最大值。

  2.假设当前答案的子集平均值是mean,那么对于这个序列中所有小于mean的元素都应该入选(可以拉低平均值),对于大于mean的元素也可能会入选(加大分母),但也是从小到大排着;因此子集除最大值外的其他部分必定是从第一个数开始的连续数字。

  3.关于子集的长度与max- mean的关系是个单峰函数,因此对子集的长度采用三分法确定

 1 #include<iostream>
 2 #include<cstdio>
 3 #define LL long long
 4
 5 using namespace std;
 6
 7 LL sum[500010],q,cur;
 8
 9 int main()
10 {
11     scanf("%d",&q);
12     while(q--)
13     {
14         int typ,aa;
15         scanf("%d",&typ);
16         if(typ==1)
17         {
18             scanf("%d",&aa);
19             sum[++cur]=sum[cur-1]+aa;
20 //            for(int i=1;i<=cur;i++)
21 //            printf("%lld ",sum[i]);
22         }
23
24         else
25         {
26             int a=sum[cur]-sum[cur-1];
27             int l=1,r=cur-1;
28
29             while(l<r)
30             {
31                 int mid2=(l+r+1)>>1,mid1=(l+mid2)>>1;
32
33                 double an1=(double)(sum[mid1]+a)/(mid1+1),an2=(double)(a+sum[mid2])/(mid2+1);
34
35                 if(an1>an2)    l=mid1+1;    else if(an2>an1)    r=mid2-1;
36                     else if(r-l>1)    r=mid2;//
37                         else break;
38
39             }
40             double ans=a-(double)(sum[l]+a)/(l+1);
41
42             printf("%.10lf\n",ans);
43         }
44     }
45
46     return 0;
47 }

   注意事项:31行,避免r=l+1时,mid2=l,mid1=l,r取不到

          37行,当相邻两个值相等的时候,已经找到答案,可以break

          36行,避免因为向下取整导致死循环;当r=l+2时,且an1=an2时,mid1=l,mid2=l+1,若更新l=mid1,则进入死循环,因此更新r=mid进一步缩小范围,然后在下一个循环break

原文地址:https://www.cnblogs.com/smoncaff/p/12293275.html

时间: 2024-08-05 03:43:02

Codeforces 939E Maximize! 离散 三分的相关文章

Codeforces 939E Maximize! (三分 || 尺取)

<题目链接> 题目大意:给定一段序列,每次进行两次操作,输入1 x代表插入x元素(x元素一定大于等于之前的所有元素),或者输入2,表示输出这个序列的任意子集$s$,使得$max(s)-mean(s)$表示这个集合的最大值与平均值的最大差值. 解题分析:首先,因为输入的$x$是非递减的,所以要使$max(s)-mean(s)$最大,肯定$max(s)$就是最后一个输入元素的大小.$x$已经确定了,现在就是尽可能的使$mean(s)$尽可能的小.如何使得平均值最小呢?肯定是从最前面的最小的元素开始

CodeForces 939E Maximize!

[题目链接] 我的做法是离线进行分治. 假设选择第$i$个数字作为最大值,那么比它小的部分的数字肯定是某个前缀,也就是要去寻找选择哪个前缀使得平均值最小. 可以发现前缀的寻找具有决策单调性,也就是说,如果选择第$i$个数字作为最大值的时候,前缀是选择了$[1, p]$:那么选择第$i$个数字之后的数字作为最大值的时候,前缀是选择肯定大于等于$p$位置.因此分治就可以了. #include <bits/stdc++.h> using namespace std; const int maxn =

Codeforces 8D Two Friends 三分+二分+计算几何

题目链接:点击打开链接 题意:点击打开链接 三分house到shop的距离,二分这条斜边到cinema的距离 #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> #include<set> #include<queue> #include<vector> #include<

codeforces 262E Simple Skewness - 三分

2017-08-02 23:12:52 writer:pprp 题目大意:给你n个数,从n个数中选取几个数,使平均数和中位数的差值最大,将选取的个数还有选取的数字找出: 算法分析:先枚举,再三分 枚举中位数,可以证明中位数一定是一个,而不是两个组成的. 三分主要用于类似于二次函数的曲线中,有极大或者极小值 代码及分析如下: #include <iostream> #include <algorithm> #include <stdio.h> #include <c

codeforces 626E. Simple Skewness 三分

题目链接 给n个数, 让你去掉一些数, 使得剩下的数的平均值-中位数的差值最大. 先将数组排序, 然后枚举每一个数作为中位数的情况, 对于每个枚举的数, 三分它的左右区间长度找到一个平均值最大的情况, 平均值最大, 肯定是它左边的数是靠近他的那几个数, 右边的数是最右边的那几个数. 然后所有情况取最大值. 三分的写法lmid = (l*2+r)/2, rmid = (l+r*2+2)/3, 学到了. 并且求平均值最好不要除,比如说平均数-中位数, 那么写成   这几个数的和-中位数*长度. 1

codeforces 578c - weekness and poorness - 三分

2017-08-27 17:24:07 writer:pprp 题意简述: ? Codeforces 578C Weakness and poorness? 给定一个序列A? 一个区间的poorness定义为这个区间内和的绝对值? weakness等于所有区间最大的poorness? 求一个x使得,序列A全部减x后weakness最小? 1 ≤ n ≤ 2 * 1e5 这里用到了最大连续区间的和的知识点·,可以看上一篇博客 通过三分找最小值 AC代码如下: /* @theme:myprogram

Codeforces Round #335 (Div. 1)--C. Freelancer&#39;s Dreams 线性规划对偶问题+三分

题意:p, q,都是整数. sigma(Ai * ki)>= p, sigma(Bi * ki) >= q; ans = sigma(ki).输出ans的最小值 约束条件2个,但是变量k有100000个,所以可以利用对偶性转化为求解 ans = p * y1 + q * y2 约束条件为: Ai * y1 + Bi * y2 <= 1 其中i为0~n-1 也就是n个约束条件. 后面三分搞搞就好了 1 #include <bits/stdc++.h> 2 using names

[codeforces 200 E Tractor College]枚举,扩展欧几里得,三分

题目出自 Codeforces Round #126 (Div. 2) 的E. 题意大致如下:给定a,b,c,s,求三个非负整数x,y,z,满足0<=x<=y<=z,ax+by+cz=s,使得f(x,y,z)=|ax-by|+|by-cz|最小 思路:枚举z,得到一个方程ax+by=s-cz,用扩展欧几里得求出这个方程的一个解,然后三分通解的整系数,求出最小f值.至于为什么可以三分画画图就清楚了,两个绝对值函数叠加在一起最多只有三种状态(第一维表示临界点较小的那个绝对值函数):(降,降)

Educational Codeforces Round 24 F. Level Generation(三分)

题目链接:Educational Codeforces Round 24 F. Level Generation 题意: 给你n个点,让你构造ans条边,使得这ans条边中至少有一半是桥. 让你求ans的最大值. 题解: 首先我们将每一个点按顺序连起来,那么可以构成n-1个桥. 然后我们可以把其中的x个点拿出来连边,这些边都不是桥. x个点最多能连x*(x-1)条边,然后剩下的n-x个点连的边将会构成桥. 然后就可以构造一个函数关系,详见check函数,然后三分一下就行了. 1 #include