wenbao与单调栈

 

 

单调栈还是挺厉害的,将n方的复杂度降为n,66666

 

 

看了别人的博客和代码慢慢理解了其中的奥妙。。自己写的第一个单调栈,

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[50], le[50], lo[50];
 4 int main(){
 5     int n, num = 0, l, r, m = -1;
 6     scanf("%d", &n);
 7     for(int i = 1; i <= n; ++i){
 8         scanf("%d", a+i);
 9     }
10     a[0] = -3, a[n+1] = -1;
11     for(int i = 1; i <= n+1; ++i){
12         if(a[i] > a[lo[num]]){
13             le[i] = i, lo[++num] = i;
14             continue;
15         }else if(a[i] == a[lo[num]]){
16             continue;
17         }
18         while(a[i] < a[lo[num]]){
19             int x = a[lo[num]]*(i-le[lo[num]]);
20             if(x > m){
21                 m = x, l = le[lo[num]], r = i-1;
22             }
23             le[i] = le[lo[num]];
24             --num;
25         }
26         lo[++num] = i;
27     }
28     printf("%d : %d - > %d\n", m, l, r);
29     return 0;
30 }

 

升级版

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[50], s[50];
 4 int main(){
 5     int n, num = 0, l, r, m = -1;
 6     scanf("%d", &n);
 7     for(int i = 1; i <= n; ++i){
 8         scanf("%d", a+i);
 9     }
10     a[0] = -3, a[n+1] = -1;
11     for(int i = 1; i <= n+1; ++i){
12         while(a[i] < a[s[num]]){
13             int x = a[s[num]] * (i-1-s[num-1]);
14             if(x > m){
15                 m = x, l = s[num-1]+1, r = i-1;
16             }
17             -- num;
18         }
19         s[++num] = i;
20     }
21     printf("%d : %d - > %d\n", m, l, r);
22     return 0;
23 }

 

 思维真是好东西。。。。。。

 

 

 

http://poj.org/problem?id=2796

 

输入:

6
3 1 6 4 5 2

输出

60
3 5

 

 1 #include <stdio.h>
 2 #define ll long long
 3 const int maxn = 1e5+2;
 4 ll sum[maxn], cnt, m = -1;
 5 int a[maxn], s[maxn], n, num, l, r;
 6 int main(){
 7     int n;
 8     scanf("%d", &n);
 9     for(int i = 1; i <= n; i++) scanf("%d", a+i), sum[i] = sum[i-1] + a[i];
10     a[0] = -3, a[n+1] = -1;
11     for(int i = 1; i <= n+1; i++){
12         while(a[i] < a[s[num]]){
13             cnt = a[s[num]] * (sum[i-1] - sum[s[num-1]]);
14             if(cnt > m){
15                 m = cnt, l = s[num-1]+1, r = i-1;
16             }
17             --num;
18         }
19         s[++num] = i;
20     }
21     printf("%lld\n%d %d\n", m, l, r);
22     return 0;
23 }

 

 

http://poj.org/problem?id=3494

找矩阵中1最多的子矩阵

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 const int maxn = 2005;
 5 int b[maxn][maxn], s[maxn];
 6 int main(){
 7     int n, m, x;
 8     while(~scanf("%d%d", &n, &m)){
 9         int mx = -1;
10         for(int i = 1; i <= n; ++i){
11             for(int j = 1; j <= m; ++j){
12                 scanf("%d", &x);
13                 if(x & 1) b[i][j] = b[i-1][j] + 1;
14                 else b[i][j] = 0;
15             }
16         }
17         for(int i = 1; i <= n; ++i){
18             int num = 0;
19             b[i][0] = -3, b[i][m+1] = -1;
20             for(int j = 1; j <= m+1; ++j){
21                 while(b[i][s[num]] > b[i][j]){
22                     int x = b[i][s[num]] * (j - 1 - s[num-1]);
23                     if(mx < x) mx = x;
24                     -- num;
25                 }
26                 s[++num] = j;
27             }
28         }
29         printf("%d\n", mx);
30     }
31     return 0;
32 }

 

 

 

http://poj.org/problem?id=3250

计算能看到牛的个数和(每只牛都往右看且只能看到小于自己的牛)

 

自己写的

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 #define ll long long
 5 const ll INF = 1e9+10;
 6 const int maxn = 80009;
 7 int a[maxn], s[maxn], n;
 8 unsigned long long m = 0;
 9 int main(){
10     int num = 0, n;
11     scanf("%d", &n);
12     for(int i = 1; i <= n; i++){
13         scanf("%d", a+i);
14     }
15     a[0] = INF+1, a[n+1] = INF;
16     for(int i = 1; i <= n+1; i++){
17         while(a[s[num]] <= a[i]){
18             m += (i-1-s[num]);
19             -- num;
20         }
21         s[++num] = i;
22     }
23     printf("%u\n", m);
24     return 0;
25 }

 

 

参考别人的代码。6666666只需要一个栈数组就好,,每次栈里面的元素就是可以看到当前牛的个数,因为栈里面的元素是严格降序排列的。。 

 

 1 #include <stdio.h>
 2 #include <iostream>
 3 int s[80003];
 4 int main(){
 5     int n, x, num = 0;
 6     long long sum = 0;
 7     scanf("%d", &n);
 8     for(int i = 0; i < n; ++i){
 9         scanf("%d", &x);
10         while(num > 0 && s[num] <= x) --num; //计算每头牛被看到的次数
11         sum += num;
12         s[++num] = x;
13     }
14     printf("%lld\n", sum);
15     return 0;
16 }

 

http://qscoj.cn/problem/11/

括号匹配求字长的匹配区间

 

 

 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <string.h>
 4 using namespace std;
 5 char str[100009];
 6 int s[100009];
 7 int main(){
 8     int n;
 9     scanf("%d", &n);
10     while(n--){
11         scanf("%s", str);
12         int num = 0, sum = 0;
13         int len = strlen(str);
14         str[len] = '*', str[len+1] = '#';
15         s[0] = len+1;
16         for(int i = 0; i <= len; ++i){
17             if(str[s[num]] == '(' && str[i] == ')'){
18                 num --;
19             }else{
20                 if(num == 0) sum = max(sum, i);
21                 else sum = max(sum, i - s[num]-1);
22                 s[++num] = i;
23             }
24         }
25         printf("%d\n", sum);
26     }
27     return 0;
28 }

 

 

只有不断学习才能进步!

 

posted @ 2018-04-14 13:45  wenbao  阅读(95)  评论(0编辑  收藏  举报