zoukankan      html  css  js  c++  java
  • hdu 3415(单调队列) Max Sum of Max-K-sub-sequence

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3415

    大意是给出一个有n个数字的环状序列,让你求一个和最大的连续子序列。这个连续子序列的长度小于等于k。

    由于是环状的数列,一般采取的措施是在数列的后面再复制一部分前面的数列;a[n]=a[0],a[n+1]=a[1]----

    用sum数组存储前i个数的和,那么对于j属于范围(i-k,i-1)来说,最大连续子序列就等于sum[i]减去在该范围内最小的sum[j]

    那么问题就变成了求在每k个范围内最小的sum[i]就行,那么就需要用到单调队列来求,队列是一个单调递增的队列,再记录一

    下区间的下标就行。

     1 #include<cstdio>
     2 #include<queue>
     3 using namespace std;
     4 const int M=210000;
     5 const int inf=0x3f3f3f3f;
     6 int sum[M],a[M];
     7 int main()
     8 {
     9     int t,n,k,i;
    10     scanf("%d",&t);
    11     while (t--){
    12         scanf("%d %d",&n,&k);
    13         sum[0]=0;
    14         for (i=1;i<=n;i++){
    15             scanf("%d",&a[i]);
    16             sum[i]=sum[i-1]+a[i];
    17         }
    18         for (i=n+1;i<n+k;i++){
    19             a[i]=a[i-n];
    20             sum[i]=sum[i-1]+a[i];
    21         }
    22         n+=k-1;
    23         int ans=-inf,s,e;
    24         deque<int>q;
    25         q.clear();
    26         for (i=1;i<=n;i++){
    27             while (!q.empty()&&q.front()<i-k)
    28                 q.pop_front();
    29             while (!q.empty()&&sum[i-1]<sum[q.back()])
    30                 q.pop_back();
    31             q.push_back(i-1);
    32             if (ans<sum[i]-sum[q.front()]){
    33                 ans=sum[i]-sum[q.front()];
    34                 s=q.front()+1;
    35                 e=i;
    36             }
    37         }//回转换成下面的数组也行
    38         /*
    39         int ans=-inf,s,e,c=1,d=0;
    40         for (i=1;i<=n;i++){
    41             while (d-c>=0&&b[c]<i-k)
    42                 c++;
    43             while (d-c>=0&&sum[i-1]<sum[b[d]])
    44                 d--;
    45             b[++d]=i-1;
    46             if (ans<sum[i]-sum[b[c]]){
    47                 ans=sum[i]-sum[b[c]];
    48                 s=b[c]+1;
    49                 e=i;
    50             }
    51         }
    52         */
    53         if (e>n-k+1) e%=(n-k+1);
    54         printf("%d %d %d
    ",ans,s,e);
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    第七周——上课笔记(一)
    第七周学习视频(二)
    第七周学习视频(一)
    第六周——上课笔记(二)
    第六周——上课笔记(一)
    第五周——上课笔记(二)
    第五周——上课笔记(一)
    第六周学习视频(一)
    iOS
    socket连接方式
  • 原文地址:https://www.cnblogs.com/JJCHEHEDA/p/5269727.html
Copyright © 2011-2022 走看看