首页 > 代码库 > 洛谷P3503 [POI2010]KLO-Blocks 单调栈

洛谷P3503 [POI2010]KLO-Blocks 单调栈

洛谷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 }

 

洛谷P3503 [POI2010]KLO-Blocks 单调栈