BZOJ4385 : [POI2015]Wilcze do?y

求出前缀和$s$,设$f[i]=s[i+d-1]-s[i-1]$。

从左到右枚举的右端点$i$,左端点$j$满足单调性,若$s[i]-s[j-1]-\max(区间内最大的f)\leq p$,则可行。

用单调队列维护即可,时间复杂度$O(n)$。

#include<cstdio>
#define N 2000010
int n,d,i,j,q[N],h,t,ans;long long p,sum,s[N],f[N];
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
int main(){
  read(n),scanf("%lld",&p),read(d);
  for(i=1;i<=n;i++)read(j),s[i]=s[i-1]+j;
  for(i=1;i<=n-d+1;i++)f[i]=s[i+d-1]-s[i-1];
  for(i=d,j=h=1;i<=n;i++){
    while(h<=t&&f[q[t]]<=f[i-d+1])t--;q[++t]=i-d+1;
    while(s[i]-s[j-1]-f[q[h]]>p)for(j++;q[h]<j;h++);
    if(i-j+1>ans)ans=i-j+1;
  }
  return printf("%d",ans),0;
}

  

时间: 2024-10-28 15:12:41

BZOJ4385 : [POI2015]Wilcze do?y的相关文章

bzoj 4385: [POI2015]Wilcze do?y

4385: [POI2015]Wilcze do?y Description 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0.请找到最长的一段连续区间,使得该区间内所有数字之和不超过p. Input 第一行包含三个整数n,p,d(1<=d<=n<=2000000,0<=p<=10^16).第二行包含n个正整数,依次表示序列中每个数w[i](1<=w[i]<=10^9). Output 包含一行一个正整数,即修改后能

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

[题目链接] 题解: 如果区间[j, i]固定,那么一定是将权值最大的一段变为0. 用单调队列维护一段区间内权值最大的子段下标(这里记录右端点下标,设为x),枚举右端点i,用尺取法计算出j. 一段区间[j, i]合法的条件是sum[i] - sum[j - 1] - (sum[x] - sum[x - d]) <= p. 复杂度: 时间复杂度:因为每个点最多遍历2次,复杂度为O(n). 空间复杂度:O(n) RE: 更新j的时候忘写h <= t了.如果写对拍的话应该可以拍出来. GET: 如果

bzoj4385 &amp; POJ2015 Wilcze do?y

Description 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0.请找到最长的一段连续区间,使得该区间内所有数字之和不超过p. Input 第一行包含三个整数n,p,d(1<=d<=n<=2000000,0<=p<=10^16).第二行包含n个正整数,依次表示序列中每个数w[i](1<=w[i]<=10^9). Output 包含一行一个正整数,即修改后能找到的最长的符合条件的区间的长度. Sample In

4385: [POI2015]Wilcze do?y

原题:http://www.lydsy.com/JudgeOnline/problem.php?id=4385 Description 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0.请找到最长的一段连续区间,使得该区间内所有数字之和不超过p. Input 第一行包含三个整数n,p,d(1<=d<=n<=2000000,0<=p<=10^16).第二行包含n个正整数,依次表示序列中每个数w[i](1<=w[i]<=

@bzoj - [email&#160;protected] [POI2015] Wilcze do?y

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个长度为 n 的序列,你有一次机会选中一段连续的长度不超过 d 的区间,将里面所有数字全部修改为 0. 请找到最长的一段连续区间,使得该区间内所有数字之和不超过 p . input 第一行包含三个整数 n, p, d (1 <= d <= n <= 2000000,0 &

bzoj4385 Wilcze do?y

Description 给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0.请找到最长的一段连续区间,使得该区间内所有数字之和不超过p. Input 第一行包含三个整数n,p,d(1<=d<=n<=2000000,0<=p<=10^16).第二行包含n个正整数,依次表示序列中每个数w[i](1<=w[i]<=10^9). Output 包含一行一个正整数,即修改后能找到的最长的符合条件的区间的长度. 单调队列扫描,记录

BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze do?y

[题解] 手残写错调了好久QAQ...... 洛谷的数据似乎比较水.. n个正整数!!这很重要 这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最大值. 枚举右端点,如果左端点到右端点的元素和减去区间内长为d的子序列中元素和的最大值,大于给定的P,那么就把左端点向右挪. #include<cstdio> #include<algorithm> #define N 2000010 #define rg register #defi

P3594 [POI2015]WIL-Wilcze do?y

———————————————————————————————————————————————————— 修改一次的单调队列,借助单调队列求出区间内删除达到的最大值,再借助连续增长的l,r求解,挺好的题 —————————————————————————————————————————————————— #include<bits/stdc++.h> using namespace std; long long a[2000005],n,p,d,sum[2000005],q[2000005],

POI2015 解题报告

未完, 待更新... Luogu3585 [POI2015]PIE Solution 模拟, 按顺序搜索, 把搜索到的需要印却没有印的点 和 印章的第一个点重合, 并印上. 另外, 纸上需要印的点 和 印章上沾墨水的点用数组储存, 能加快很多 Code 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #define R register 6 u