• 【单调队列】【3-21个人赛】【problmeB】


    Problem B

    Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
    Total Submission(s) : 170   Accepted Submission(s) : 29

    Font: Times New Roman | Verdana | Georgia

    Font Size:  

    Problem Description

    WKC有N个排成一排的灯泡,亮度分别为(A1,A2,……,An)。他希望从中找出一段连续的个数不小于A,且不超过B的灯泡,使得这些灯泡的亮度和S最大。
    例如6个亮度为: 1, -3, 5, 1, -2, 3的灯泡,
    当A=2,B=2或3时 S=5+1=6
    当A=3,B=4时 S=5+1+(-2)+3=7

    Input

    第一行为一个整数T,表示有T组测试数组(T<=10)。
    接下来为T组数组,每组的格式为:
    第一行三个整数N,A,B(1<=A<=B<=N<=500000)。
    第二行为N个整数,每个整数用空格隔开,表示这N个灯泡的亮度。|亮度|<=10000。

    Output

    对每组测试数据,输出一行,为所求的最大值S。

    Sample Input

    2
    6 2 2
    1 -3 5 1 -2 3
    6 3 4
    1 -3 5 1 -2 3
    

    Sample Output

    6
    7
    


    sum[i]存前缀和

         枚举连续序列的初始点 并找到【初始点+A-1,初始点+B-1】区间中的sum[i]的最大值 更新ANS即可

         复杂度N*(B-A)

        但是我们可以看出 在找最大值时 这个区间是固定不动的,而且随着枚举初始点向左移,所以可以用单调队列来维护这个区间最大值

        是单调队列的一个常用法


        单调队列介绍在这里

       http://blog.csdn.net/justmeh/article/details/5844650


       1.不加二分

       

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    const int maxn=500000+5;
    using namespace std;
    struct node
    {
        long long num;
        int pos;
    };
    long long N,A,B;
    long long a[maxn],sum[maxn];
    node queue[maxn];
    int s=1,t=0;
    void init()
    {
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    }
    void input()
    {
        s=1;t=0;
        scanf("%d%d%d",&N,&A,&B);
        for(int i=1;i<=N;i++)
        {
            scanf("%I64d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
    }
    void PUSH(long long aa,int bb)
    {
        while(t!=s-1&&queue[t].num<=aa) t--;
        queue[++t].num=aa,queue[t].pos=bb;
    }
    void solve()
    {
        long long ans;
        for(int i=A;i<=B;i++)
        PUSH(sum[i],i);
        ans=queue[s].num-sum[0];
        for(int i=2;i+A-1<=N;i++)
        {
            if(i+B-1<=N)
            PUSH(sum[i+B-1],i+B-1);
            while(queue[s].pos<i+A-1)
                s++;
            if(ans<queue[s].num-sum[i-1])ans=queue[s].num-sum[i-1];
        }
        printf("%I64d
    ",ans);
    }
    int main()
    {
    //	init();
    	int T;
    	cin>>T;
    	while(T--)
        {
            input();
            solve();
        }
        return 0;
    }
    

       2.加二分

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    const int maxn=500000+5;
    using namespace std;
    struct node
    {
        long long num;
        int pos;
    };
    long long N,A,B;
    long long a[maxn],sum[maxn];
    node queue[maxn];
    int s=1,t=0;
    void init()
    {
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    }
    void input()
    {
        s=1;t=0;
        scanf("%d%d%d",&N,&A,&B);
        for(int i=1;i<=N;i++)
        {
            scanf("%I64d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
    }
    int FIND(int s,int t,int p)
    {
        int m;
        while(s<t)
        {
            int m=(s+t)/2;
            if(queue[m].num<p) t=m;
            else s=m+1;
        }
        if(queue[s].num<=p) return s-1;
        else return s;
    }
    void PUSH(long long aa,int bb)
    {
        int k=0;
        if(s>t)
        queue[++t].num=aa,queue[t].pos=bb;
        else {
                t=FIND(s,t,aa);
                queue[++t].num=aa,queue[t].pos=bb;
              }
    }
    void solve()
    {
        long long ans;
        for(int i=A;i<=B;i++)
        PUSH(sum[i],i);
        ans=queue[s].num-sum[0];
        for(int i=2;i+A-1<=N;i++)
        {
            if(i+B-1<=N)
            PUSH(sum[i+B-1],i+B-1);
            while(queue[s].pos<i+A-1)
                s++;
            if(ans<queue[s].num-sum[i-1])ans=queue[s].num-sum[i-1];
        }
        printf("%I64d
    ",ans);
    }
    int main()
    {
    //	init();
    	int T;
    	cin>>T;
    	while(T--)
        {
            input();
            solve();
        }
        return 0;
    }
    


  • 相关阅读:
    poj 1087 A Plug for UNIX
    poj 1149 : PIGS
    自己制作的我们学校的校园无线网自动登录程序(C#实现)
    poj 1067取石子(威佐夫博奕)
    poj 1088滑雪
    SQL Server 2005 系统数据介绍:sys.dm_exec_requests
    一票难求:我为铁道部献计献策!
    Integration Services 学习(7):包部署
    Integration Services 学习(8):事务
    Integration Services包部署常见问题汇总
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480405.html
Copyright © 2020-2023  润新知