• 2017.3.18【NOIP提高组】模拟赛B组 T1:人类基因组


    **【NOIP2013模拟联考15】人类基因组(genes) **

    Description

    L教授最近正在研究一个关于人类基因的项目,基因可以被看作一个长度为N的序列:A0,A1,…,An-1。对于这个基因序列循环移动k位之后,就可以得到一个新的基因序列为:Ak,Ak+1,…,An-1,A0,A1,…,Ak-1。当一个基因序列满足对于任意的前i(1<=i<=n)项和都满足不小于0,我们就称这个基因序列为优质基因序列。

    由于L教授最近工作比较繁忙,所以找到了正在实验室闲逛的你,你的任务就是帮L教授统计出所有优质基因序列的个数。

    Input

    第一行一个整数n,表示基因序列的长度。

    第二行n个整数,依次为A0,A1,…,An-1的值。

    Output

    输出仅一个整数,表示优质基因序列的个数。

    Sample Input

    输入1:

    3

    2 2 3

    输入2:

    5

    3 -1 2 -3 4

    Sample Output

    输出1:

    3

    【样例1说明】

    3个元素的序列:2 2 3,循环移动情况如下:

    循环移动0位得到序列:2 2 3,前i项和分别为:2 4 7,符合条件;

    循环移动1位得到序列:2 3 2,前i项和分别为:2 5 7;符合条件;

    循环移动2位得到序列:3 2 2,前i项和分别为:3 5 7;符合条件;

    输出2:

    2

    Data Constraint

    对于30%的数据,满足1<=N<=5,000

    对于50%的数据,满足1<=N<=10,000

    对于100%的数据,满足1<=N<=1,000,000,-1,000<=Ai<=1,000

    题解:
    【题目分析】
    把给出的序列复制两份构成:
    A[0]、A[1]、…、A[n-1]、A[n]、A[n+1]、…、An+n-1
    则循环移动K位后的序列就是上面序列的:A[k],A[k+1],…,A[k+n-1]。
    设sum[i]=A[0]+A[1]+…+A[i],则循环K位后序列的任意前p项的和为:sum[k+p]-sum[k-1];
    由此可知:判断环移动K位后的序列任意前p项和都不小于0,只判断最小的sum[k+p]与sum[k-1]的差大于等于0即可。
    至于找最小的sum[k+p],可以用下列数据结构之一进行优化:
    1、线段树:时间复杂度O(2nlog2n);
    2、优先队列:时间复杂度O(2nlog2n);
    3、单调队列:时间复杂度O(2n);
    标程:

    
    var
            i,j,k,l,n,m,ans,gb:longint;
            a,sum,f1,f2:array[0..1000000] of longint;
    begin
            assign(input,'genes.in');reset(input);
            assign(output,'genes.out');rewrite(output);
            readln(n);
            for i:=1 to n do
            begin
                    read(a[i]);
                    sum[i]:=sum[i-1]+a[i];
            end;
            f1[1]:=1;f2[n]:=n;
            for i:=2 to n do
            begin
                    if sum[i]<sum[f1[i-1]] then
                            f1[i]:=i
                    else
                            f1[i]:=f1[i-1];
            end;
            for i:=n-1 downto 1 do
            begin
                    if sum[i]<sum[f2[i+1]] then
                            f2[i]:=i
                    else
                            f2[i]:=f2[i+1];
            end;
            if sum[f1[n]]>=0 then inc(ans);
            for i:=2 to n do
            begin
                    if (sum[f2[i]]-sum[i-1]>=0) and (sum[f1[i-1]]-sum[i-1]+sum[n]>=0) then inc(ans);
            end;
            writeln(ans);
    end.
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    如何学习区块链
    用Python从零开始创建区块链
    区块链入门
    什么是区块链
    localStorage使用总结
    整理vue学习笔记
    SCSS 教程
    vue — 创建vue项目
    软件开发的常见文档
    史上最全的CSS hack方式一览(转)
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148442.html
Copyright © 2020-2023  润新知