zoukankan      html  css  js  c++  java
  • bzoj2086【Poi2010】Blocks

    因为long long还有PE的事WA了一下午TAT

    考虑一段可行区间的平均值肯定>=k

    也就是说将每个数减去k以后,一段可行区间的和非负,求一段最长区间。

    一段区间的和肯定是两个前缀和的差

    先求出前缀和,考虑要想让答案更优,被减数应该靠后而且大,减数应该靠前而且小

    so维护两个单调队列然后two-pointers扫一遍就好了QwQ~

    记得输出行末必须换行&不能有空格

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define int long long
    using namespace std;
    const int Mx=1000010;
    struct Node { int val,num; } stk1[Mx],stk2[Mx];
    int n,m,cnt1,cnt2,c[Mx],num[Mx],sum[Mx];
    void solve(int k)
    {
        cnt1=0,cnt2=0;
        memset(stk1,0,sizeof(stk1));
        memset(stk2,0,sizeof(stk2));
        int tmp=-898892147483647LL,ans=0;
        for(int i=1;i<=n;i++) num[i]=c[i]-k;
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+num[i];
        for(int i=n;i>=1;i--) if(sum[i]>tmp) stk1[++cnt1].val=sum[i],stk1[cnt1].num=i,tmp=sum[i];
        tmp=2147889998483647LL;
        for(int i=0;i<=n;i++) if(sum[i]<tmp) stk2[++cnt2].val=sum[i],stk2[cnt2].num=i,tmp=sum[i];
        for(int st=cnt1,to=1;st>=1&&to<=cnt2;st--)
        {
            while(1)
            {
                if(stk1[st].val-stk2[to].val>=0)
                {
                    ans=max(ans,stk1[st].num-stk2[to].num);
                    break;
                }
                else to++;
            }
        }
        printf("%lld",ans);
    }
    signed main()
    {
        //freopen("1.in","r",stdin);
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&c[i]);
        while(m--)
        {
            int k;scanf("%lld",&k);
            solve(k);
            if(m)printf(" ");
            else puts("");
        }
        return 0;
    }
  • 相关阅读:
    POI简单初识 Demo (资源来自网络本人属于收藏总结)
    spring学习笔记(6)装配Bean 的种类和区别 【资源来自网络 版权非本人】
    springboot相关
    前沿技术Hyperledger
    MAC版的IDEA快捷键
    JSONObject put,accumulate,element的区别
    1027
    position窗口居中
    http 请求详解大全
    关于Spring注解
  • 原文地址:https://www.cnblogs.com/xiaoxubi/p/6160176.html
Copyright © 2011-2022 走看看