zoukankan      html  css  js  c++  java
  • 数字游戏

    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;
    }
  • 相关阅读:
    idea配置SOLServer错误解决记录
    精确的double加减乘除运算工具类
    Java类型转换工具类(十六进制—bytes互转、十进制—十六进制互转,String—Double互转)
    rest的Web服务端获取http请求头字段
    前端开发规范:1-通用规范
    一些webpack常见编译报错的解决方案
    常用的数组对象操作方法
    理解ES6的新数据类型:Symbol
    canvas在vue中的应用
    vue-cli3+typescript+路由懒加载报错问题
  • 原文地址:https://www.cnblogs.com/yanshannan/p/7413143.html
Copyright © 2011-2022 走看看