【CodeForces】578 C. Weakness and Poorness

【题目】C. Weakness and Poorness

【题意】给定含n个整数的序列ai,定义新序列为ai-x,要使新序列的最大子段和绝对值最小,求实数x。n<=2*10^5。

【算法】二分||三分||计算几何(凸包)

【题解】Editorial

令正数最大子段和为A,负数最大子段和为B,绝对值是max(A,B)。当x从小到大变化时,A由大变小,B由小变大。

容易发现这是一个下凸函数,可以用三分法求解。

但是,这道题卡精度(-11会WA,-12会T),解决方法是根据复杂度把循环次数卡到极限而不用r-l<=eps的方法,以及缩小一开始的l和r范围防卡。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#define ll long long
#define lowbit(x) x&-x
using namespace std;
int read(){
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c=='-')t=-1;
    do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    return s*t;
}
int ab(int x){return x>0?x:-x;}
//int MO(int x){return x>=MOD?x-MOD:x;}
//void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
/*------------------------------------------------------------*/
const int maxn=200010;
const double eps=1e-9;

int n;
double a[maxn],b[maxn];

double F(double x){
    for(int i=1;i<=n;i++)b[i]=a[i]-x;
    double sum=0,ans=0;
    for(int i=1;i<=n;i++){
        sum+=b[i];
        if(sum<0)sum=0;
        ans=max(ans,sum);
    }
    sum=0;
    for(int i=1;i<=n;i++){
        sum+=b[i];
        if(sum>0)sum=0;
        ans=max(ans,-sum);
    }
    return ans;
}
int main(){
    n=read();
    double m1,m2,l=-10010,r=10010;
    for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
    for(int i=1;i<=100;i++){
        m1=l+(r-l)/3;m2=l+(r-l)/3*2;
        if(F(m1)<F(m2))r=m2;else l=m1;
    }
    printf("%.10lf",F(l));
    return 0;
}
View Code

 

进一步观察,发现答案出现在A=B时,当x偏小时A>B,当x偏大时A<B,那么可以二分求解。

最后的几何解法,将max(si-sj)展开后化为以x为自变量,y为绝对值的一些直线,然后求上下凸包。

 

 

转载于:https://www.cnblogs.com/onioncyc/p/8005275.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces Round 894 (Div. 3) 是一个Codeforces举办的比赛,是第894轮的Div. 3级别比赛。它包含了一系列题目,其中包括题目E. Kolya and Movie Theatre。 根据题目描述,E. Kolya and Movie Theatre问题要求我们给定两个字符串,通过三种操作来让字符串a等于字符串b。这三种操作分别为:交换a中相同位置的字符、交换a中对称位置的字符、交换b中对称位置的字符。我们需要先进行一次预处理,替换a中的字符,然后进行上述三种操作,最终得到a等于b的结果。我们需要计算预处理操作的次数。 根据引用的讨论,当且仅当b[i]==b[n-i-1]时,如果a[i]!=a[n-i-1],需要进行一次操作;否则不需要操作。所以我们可以遍历字符串b的前半部分,判断对应位置的字符是否与后半部分对称,并统计需要进行操作的次数。 以上就是Codeforces Round 894 (Div. 3)的简要说明和题目E. Kolya and Movie Theatre的要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Codeforces Round #498 (Div. 3) (A+B+C+D+E+F)](https://blog.csdn.net/qq_46030630/article/details/108804114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Codeforces Round 894 (Div. 3)A~E题解](https://blog.csdn.net/gyeolhada/article/details/132491891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值