洛谷P3503 [POI2010]KLO-Blocks
单调栈
首先 因为每个数都要大于k 所以说,我们就可以先将每一个数减去k,
然后求他们 的前缀和, 这样问题就转化成了求sum[ r ] - sum[ l ] 运用前缀和
然后 这样的长度 就是 r-l
然后我们考虑怎么求这个最大
首先我们发现 当 i < j 且 sum[ i ] < sum[ j ] 那么 i 一定是 优于 j 的
所以 我们就可以把这些 j 给 忽略 掉了
也就是说 我们 开个单调栈 在 i < j 的情况下 保持 sum[ i ] 降序
然后 我们 从 右向左枚举 r 我们发现在 r 枚举过去时 为了保证答案的最优性
我们的 l 也必须 时 单调的 ,单调下降 这样以确保答案的最优性
1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 #include <iomanip> 9 #define ll long long 10 using namespace std ; 11 12 const int maxn = 1000011 ; 13 int n,m,x,top,ans ; 14 int stack[maxn],a[maxn] ; 15 ll sum[maxn] ; 16 17 inline ll read() 18 { 19 ll x = 0 , f = 1 ; 20 char ch = getchar() ; 21 while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 22 while(ch>='0'&&ch<='9') { x = x * 10+ch-48 ; ch = getchar() ; } 23 return x * f ; 24 } 25 26 inline ll write(ll x ) 27 { 28 while(x<0) x = -x,putchar('-') ; 29 if(x>9) write(x/10) ; 30 putchar(x % 10 +48) ; 31 } 32 33 inline void solve(int x) 34 { 35 int j ; 36 ans = 0 ; 37 for(int i=1;i<=n;i++) 38 sum[ i ] = sum[ i-1 ] + a[ i ] -x ; 39 stack[ 0 ] = 0 ; 40 top = 0 ; 41 for(int i=1;i<=n;i++) 42 if(sum[ stack[top] ] > sum[ i ]) 43 stack[++top] = i ; 44 j = top + 1 ; 45 for(int i=n;i>=1;i--) 46 { 47 while ( j && sum[ i ] >= sum[ stack[ j-1 ] ] ) j-- ; 48 ans = max( i - stack[ j ],ans ) ; 49 } 50 write(ans) ; 51 putchar(' ') ; 52 } 53 54 int main() 55 { 56 n = read() ; m = read() ; 57 for(int i=1;i<=n;i++) 58 a[ i ] = read() ; 59 for(int i=1;i<=m;i++) 60 { 61 x = read() ; 62 solve(x) ; 63 } 64 65 return 0 ; 66 }