zoukankan      html  css  js  c++  java
  • [POI2015]WIL-Wilcze doły

    题目描述

    给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0。请找到最长的一段连续区间,使得该区间内所有数字之和不超过p。

    输入格式:

    第一行包含三个整数n,p,d(1<=d<=n<=2000000,0<=p<=10^16)。第二行包含n个正整数,依次表示序列中每个数wi

    输出格式:

    包含一行一个正整数,即修改后能找到的最长的符合条件的区间的长度。

    题解:

    发现,肯定要选择最多的d变成0,不然不优。并且,如果以i作为结尾,左端点为j的话,那么如果以i+1作为结尾,左端点不可能比j小。

    所以,可以用一个双指针,维护L,R,

    L、R为一个合法区间条件是,L~R的数的和,减去最大的长度为d的和,总和少于等于p

    对于给定R,L不满足的时候,就把L右移即可。

    至于L~R中长度等于d的最大的和,可以用一个单调队列维护。

    复杂度O(n)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2000000+10;
    int n,d;
    ll p;
    int ans;
    int q[N],l,r;
    ll sum[N],a[N];
    int main()
    {
        scanf("%d%lld%d",&n,&p,&d);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        int L=1,R=1;
        l=1,r=0;
        q[++r]=d;
        for(R=d;R<=n;R++){
            //cout<<R<<endl;
            while(sum[R]-sum[L-1]-(sum[q[l]]-sum[q[l]-d])>p){
                L++;
                while(l<=r&&q[l]-d+1<L) l++;
            }
            
            if(l<=r&&sum[R]-sum[L-1]-(sum[q[l]]-sum[q[l]-d])<=p) ans=max(ans,R-L+1);
            //cout<<L<<endl;
            if(R!=n){
                while(l<=r&&sum[R+1]-sum[R+1-d]>sum[q[r]]-sum[q[r]-d]) r--;
                q[++r]=R+1;
            }
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    cocos2d3.8.1 使用prebuild提升发布android速度
    AS3条件编译
    Box2d FilterData
    旋转关节(Revolute Joint)
    线关节(Line Joint)
    平移关节(Prismatic Joint)
    滑轮关节(b2PulleyJoint)
    PAT Basic 1043 输出PATest (20 分)
    PAT Basic 1042 字符统计 (20 分)
    PAT Basic 1039 到底买不买 (20 分)
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9656091.html
Copyright © 2011-2022 走看看