• 数字游戏


    Description

    按顺序给出n个数的数列,现在需要从中求出连续几个数的和的最大,连续的数的个数要在s和t之间。

    Input

    第一行有三个正整数n、s和t ,同上描述。
    接下来有n行,每行一个整数ai,组成数列,数列的顺序不可以变换。

    Output

    输出长度在s和t之间连续的数列数的和的最大值。

    Sample Input

    5 2 3
    1
    -2
    3
    -4
    5

    Sample Output

    4

    Hint

    对于30%数据,1<=s<=t<=n<=100
    对于100%数据,1<=s<=t<=n<=100,000
    对于 100%数据,|ai|<=10000

    【题解】

    不知为什么为此题纠结了好久。。。估计是很少用单调队列吧。。。

    这道题即使用了前缀和,O(n*abs(s-t))肯定超时,只有40分,因此我们要用单调队列维护在以i为结尾的当前状态下,减去的最小前缀和,从而使结果最大。过程是不断加入减去后状态合法的前缀和,最前面突变成不合法的舍弃,后面比最前面大的舍弃(反正没用)。

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define fp(i,a,b) for(int i=a;i<=b;i++)
    #define fq(i,a,b) for(int i=a;i>=b;i--)
    #define il inline
    #define ll long long 
    using namespace std;
    ll n,s,t,a[100005]={},sum[100005]={},line[10000005]={},ans,head,tail;
    il int gi()
    {
       int x=0;
       short int t=1;
       char ch=getchar();
      while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
      if(ch=='-') t=-1,ch=getchar();
      while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
      return x*t;
    }
    int main()
    {
        n=gi();s=gi();t=gi();
        fp(i,1,n) a[i]=gi(),sum[i]=sum[i-1]+a[i];
        head=1;tail=0;sum[0]=0;line[1]=0;
        fp(i,s,n)
        {
            while(head<=tail&&sum[line[tail]]>=sum[i-s]) tail--;
            line[++tail]=i-s;
            while(line[head]<(i-t)) head++;
            ans=max(ans,sum[i]-sum[line[head]]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    C语言程序设计_zju——计算时间差
    C语言程序设计_zju——第1周编程练习_逆序的三位数
    常用CMD指令
    C#MVC Razor的Ajax.BeginForm里面的OnSuccess未执行(未成功跳转)
    发布带注释的dll
    读书笔记之《得未曾有》
    读书笔记之《高效人士的七个习惯》
    读书笔记之《好好说话》
    个人随笔之《关于选择》
    个人随笔之《关于心安》
  • 原文地址:https://www.cnblogs.com/yanshannan/p/7413143.html
Copyright © 2020-2023  润新知