关闭

[bzoj4385/POI2015]Wilcze doły

248人阅读 评论(0) 收藏 举报

Description

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

Data Constraint

1≤d≤n≤2000000,0≤p≤10^16
每个数w[i]满足1≤w[i]≤10^9

分析

首先考虑一个区间[i,j],如果j-i≤d,那么显然把区间的元素全部变成0就是最优的。
如果j-i>d,那么要找到一个x,满足i≤x,x+d-1≤j,并且区间[i,j]的和减去[x,x+d-1]的和最小。设数组s为序列的前缀和,那么如果满足条件s[i]-s[j-1]-max(s[x+d-1]-s[x-1])≤p,区间[i,j]是可以更新答案的。
可以枚举区间的右端j,那么显然,满足条件的最小的i是随着j变大而变大的。
然后剩下的就是区间最大值了。
n达到了2000000,所以应该用O(n)的算法。考虑到i和j都是递增的,用单调队列维护即可。

/**************************************************************
    Problem: 4385
    User: worldwide
    Language: C++
    Result: Accepted
    Time:5796 ms
    Memory:24260 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn=2000005;

typedef long long LL;

int n,d,j,h,t,data[maxn],ans;

LL s[maxn],p;

char c;

int read()
{
    for (c=getchar();c<'0' || c>'9';c=getchar());
    int x=c-48;
    for (c=getchar();c>='0' && c<='9';c=getchar()) x=x*10+c-48;
    return x;
}

LL getmax()
{
    for (;h<=t && data[h]-d<j;h++);
    if (h>t) return 1e16;
    return s[data[h]]-s[data[h]-d];
}

int main()
{
    n=read(); scanf("%lld",&p); d=read();
    for (int i=1;i<=n;i++) s[i]=s[i-1]+read();
    ans=d;
    h=1;
    for (int i=d;i<=n;i++)
    {
        for (;h<=t && s[data[t]]-s[data[t]-d]<s[i]-s[i-d];t--);
        data[++t]=i;
        for (;s[i]-s[j]-getmax()>p;j++);
        if (i-j>ans) ans=i-j;
    }
    printf("%d\n",ans);
    return 0;
}
0
0
查看评论

BZOJ4385[POI2015] Wilcze doły

BZOJ4385[POI2015] Wilcze doły Description 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0。 请找到最长的一段连续区间,使得该区间内所有数字之和不超过p。 ...
  • zqh_wz
  • zqh_wz
  • 2016-10-12 11:13
  • 187

BZOJ4385: [POI2015]Wilcze doły

水题。。 反正就是丢到一个单调队列里去然后每次都弹出就好了。。 #include #include #include using namespace std; char c; inline void read(int &a) { a=0;do c=getchar();while(c&...
  • liutian429073576
  • liutian429073576
  • 2016-01-23 09:24
  • 452

【bzoj4385】 [POI2015]Wilcze doły

Description 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0。 请找到最长的一段连续区间,使得该区间内所有数字之和不超过p。 Input 第一行包含三个整数n,p,d(1 第二行包含n个正整数,依次表示序列中每个数w[...
  • Timothy023
  • Timothy023
  • 2017-07-27 11:28
  • 93

BZOJ4385 POI2015 Wilcze doły

POI2015 Wilcze doły
  • Kanosword
  • Kanosword
  • 2016-10-18 11:04
  • 237

bzoj4385 [POI2015]Wilcze doły

题目bzoj上的单调栈第一题,维护一个单调栈,让里面长度为d,再更新答案。#include<bits/stdc++.h> #define N 2000005 using namespace std; long long n,p,d; long long A[N+1],st,ans; l...
  • wanherun
  • wanherun
  • 2017-09-22 22:46
  • 90

bzoj4385 Wilcze doły 单调队列

(赶脚POI要被权限。。赶紧趁现在刷几道水题)。        首先令s[i]表示(1,i)序列的和。现在考虑一段序列(i,j),如何判断这段序列是否满足条件呢?当j-i+1        因此我们枚举右端点j,显然i随...
  • lych_cys
  • lych_cys
  • 2016-03-03 15:07
  • 783

4385: [POI2015]Wilcze doły

4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 682  Solved: 282 [Submit][Statu...
  • CRZbulabula
  • CRZbulabula
  • 2016-12-31 10:39
  • 146

【BZOJ4385】[POI2015]Wilcze doły【单调队列】【前缀和】【Two Pointers】

【题目链接】 题解: 如果区间[j, i]固定,那么一定是将权值最大的一段变为0。 用单调队列维护一段区间内权值最大的子段下标(这里记录右端点下标,设为x),枚举右端点i,用尺取法计算出j。 一段区间[j, i]合法的条件是sum[i] - sum[j - 1] - (sum[x] - ...
  • BraketBN
  • BraketBN
  • 2016-05-09 17:05
  • 648

BZOJ 4385: [POI2015]Wilcze doły 单调队列

单调队列
  • neighthorn
  • neighthorn
  • 2016-11-10 17:37
  • 342

bzoj 4385: [POI2015]Wilcze doły 单调队列

题意给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0。 请找到最长的一段连续区间,使得该区间内所有数字之和不超过p。 1<=d<=n<=2000000,0<=p<=10^16,1<=w[i]<=10^9分析...
  • qq_33229466
  • qq_33229466
  • 2017-04-24 20:25
  • 309
    个人资料
    • 访问:74169次
    • 积分:2755
    • 等级:
    • 排名:第15510名
    • 原创:198篇
    • 转载:0篇
    • 译文:0篇
    • 评论:32条
    最新评论