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

<题目链接>

题目大意:
给定一段序列,每次进行两次操作,输入1 x代表插入x元素(x元素一定大于等于之前的所有元素),或者输入2,表示输出这个序列的任意子集$s$,使得$max(s)-mean(s)$表示这个集合的最大值与平均值的最大差值。

解题分析:
首先,因为输入的$x$是非递减的,所以要使$max(s)-mean(s)$最大,肯定$max(s)$就是最后一个输入元素的大小。$x$已经确定了,现在就是尽可能的使$mean(s)$尽可能的小。如何使得平均值最小呢?肯定是从最前面的最小的元素开始选,因为最后一个元素是一定要选的(选做最大的元素),所以$mean(s)$函数必然是一个下凹的函数(在开始选小的元素时,平均值会被慢慢的拉低(因为一开始只有一个最大的元素),选到后面比较大的元素时,平均值又会逐渐上升)。所以我们可以用三分寻找max(s)-mean(s)函数的峰值。同时本题也可以用尺取来做,也是用来寻找峰值。

三分:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 5e5+5;
ll sum[N];

template<typename T>
inline void read(T&x){
    x=0;int f=1;char c=getchar();
    while(c<‘0‘ || c>‘9‘){ if(c==‘-‘)f=-1;c=getchar(); }
    while(c>=‘0‘ && c<=‘9‘){ x=x*10+c-‘0‘;c=getchar(); }
    x*=f;
}
inline double cal(int loc,int x){
    return (double)(sum[loc]+x)/(loc+1);
}
int main(){
    int q;read(q);
    int op,x,cnt=0;
    while(q--){
        read(op);
        if(op==1){
            read(x);
            sum[++cnt]=sum[cnt-1]+x;
        }else{
            //对前cnt-1个元素进行三分
            int l=1,r=cnt-1;
            while(l<r){
                int m1=(l+l+r)/3,m2=(l+r+r)/3;
                if(cal(m1,x)>=cal(m2,x)){
                    if(l==m1)break;
                    l=m1;
                }else{
                    if(r==m2)break;
                    r=m2;
                }
            }
            double ans=(double)(sum[l]+x)*1.0/(l+1);
            for(int i=l;i<=r;i++)ans=min(ans,(double)(sum[i]+x)/(i+1));     //因为最后[l,r]之间可能不只有一个元素
            printf("%.10lf\n",x-ans);
        }
    }
}

尺取:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 5e5+5;
ll sum[N];

template<typename T>
inline void read(T&x){
    x=0;int f=1;char c=getchar();
    while(c<‘0‘ || c>‘9‘){ if(c==‘-‘)f=-1;c=getchar(); }
    while(c>=‘0‘ && c<=‘9‘){ x=x*10+c-‘0‘;c=getchar(); }
    x*=f;
}
inline double cal(int loc,int x){
    return (double)(sum[loc]+x)/(loc+1);
}
int main(){
    int q;read(q);
    int op,x,cnt=0,top=0;
    while(q--){
        read(op);
        if(op==1){
            read(x);
            sum[++cnt]=sum[cnt-1]+x;
        }else{
            while(top<cnt){
                if(cal(top+1,x)<cal(top,x))top++;
                else break;
            }
            printf("%.10lf\n",x-cal(top,x));
        }
    }
}

原文地址:https://www.cnblogs.com/00isok/p/10691637.html

时间: 2024-10-04 04:13:44

Codeforces 939E Maximize! (三分 || 尺取)的相关文章

Codeforces 939E Maximize! 离散 三分

题目传送门↓http://codeforces.com/problemset/problem/939/E 题意:有一最初为空的不下降序列,有两种操作,一种是在序列里增加一个不小于序列尾的整数,另一种是查询当前序列中的某个子集,其最大值为max,平均值为mean,使得子集的max-mean在当前序列的所有子集中最大,输出这个max-mean. 思考: 1.序列最大值是否入选,假设不入选,则此时答案的子集中,最大值为max1,和为sum1,元素个数为k则答案可表示为max1 - sum1 / k:若

CodeForces 939E Maximize!

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

Codeforces Round #116 (Div. 2, ACM-ICPC Rules) E. Cubes (尺取)

题目链接:http://codeforces.com/problemset/problem/180/E 给你n个数,每个数代表一种颜色,给你1到m的m种颜色.最多可以删k个数,问你最长连续相同颜色的序列的长度是多少. 将相同颜色的下标存到对应颜色的容器中,比如ans[a[i]].push_back(i)就是将下标为i颜色为a[i]的数存到ans[a[i]]容器中. 对于每种颜色序列,尺取一下 在差距小于k的情况下取能取到的最大长度. 1 //#pragma comment(linker, "/S

Educational Codeforces Round 53 (Rated for Div. 2) C. Vasya and Robot 【二分 + 尺取】

任意门:http://codeforces.com/contest/1073/problem/C C. Vasya and Robot time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Vasya has got a robot which is situated on an infinite Cartesian plane, i

Codeforces Round #451 (Div. 2)【A,B,C,D,E】【C题:模拟 D题:尺取+贪心 E题:思维+优先队列维护最值】

特判最后一位即可 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 #define int long long 5 6 signed main(){ 7 int n;cin>>n;int t=n%10; 8 if(t==0) cout<<n; 9 else if(t>5) { 10 cout<<(n+10-t); 11 } 12 else { 13 cout<<(n-t); 14 }

POJ3061 Subsequence 尺取or二分

Description A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements o

POJ3320 Jessica&#39;s Reading Problem(尺取+map+set)

POJ3320 Jessica's Reading Problem set用来统计所有不重复的知识点的数,map用来维护区间[s,t]上每个知识点出现的次数,此题很好的体现了map的灵活应用 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #include <vector> #include &

hdu 4123 Bob’s Race 树的直径+rmq+尺取

Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads

poj2566尺取变形

Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronautic and Space Administration (that must be going through a defiant phase: "But I want to use feet, not meters!"). Each signal seems to come in two