From easthong☆holiday
描述 Description
经过几个月辛勤的工作,FJ决定让奶牛放假。假期可以在1…N天内任意选择一段(需要连续),每一天都有一个享受指数W。但是奶牛的要求非常苛刻,假期不能短于P天,否则奶牛不能得到足够的休息;假期也不能超过Q天,否则奶牛会玩的腻烦。FJ想知道奶牛们能获得的最大享受指数。
输入格式 Input Format
第一行:N,P,Q.
第二行:N个数字,中间用一个空格隔开。
输出格式 Output Format
一个整数,奶牛们能获得的最大享受指数。
样例输入 Sample Input
2 4
-9 -4 -3 8 -6
样例输出 Sample Output
Hint
选择第3-4天,享受指数为-3+8=5。
时间限制 Time Limitation
1s
注释 Hint
50% 1≤N≤10000
100% 1≤N≤100000
1<=p<=q<=n
本题提供两种思路
1.线段树 复杂度(nlogn)
2.单调队列 复杂度(n)
具体实现
1.线段树:
首先预处理出来sum前缀和,
对于每一点i,我们只需要找到符合题意范围内最小的即可
并放入线段树中
对去查询每一个点,用线段树去查询i-q+1~i-p+1之间的最小值
然后去更新最大值
2.单调队列:
构造一个单调队列
当枚举到i的时候,用sum[i-p+1]去更新队列
具体实现看代码
#include <bits/stdc++.h> #define ll long long using namespace std; inline ll read(){ ll x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=1e6+10; namespace zhangenming{ ll q[MAXN],head=1,tail=0,a[MAXN],maxn=-10000000000000,sum[MAXN]={},n,p,qq; void init(){ n=read();p=read();qq=read(); for(int i=1;i<=n;i++){ a[i]=read(); sum[i]=sum[i-1]+a[i]; //cout<<sum[i]<<' '; } //cout<<endl; } void solve(){ q[++tail]=0; for(int i=p;i<=n;i++){ while(head<=tail&&i-q[head]>qq) head++; //cout<<i<<' '<<q[head]<<' '; ll tn=sum[i]-sum[q[head]]; //cout<<tn<<endl; maxn=max(maxn,tn); //cout<<maxn<<endl; tn=i-p+1; while(sum[tn]<=sum[q[tail]]&&head<=tail) tail--; q[++tail]=tn; } cout<<maxn<<endl; } } int main(){ //freopen("ab.in","r",stdin); //freopen("ab.out","w",stdout); using namespace zhangenming; init(); solve(); return 0; }