zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    %d %d
    ", 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
    ", 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
    ", 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
    ", 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
    ", sum);
    26     }
    27     return 0;
    28 }

    只有不断学习才能进步!

  • 相关阅读:
    杯具,丢失了一部分邮件
    Android Building System 总结
    build/envsetup.sh
    PhoneApp是什么时候被创建的
    测试电信的WAP PUSH的方法
    修改Activity响应音量控制键修改的音频流
    ril崩溃时的出错地址定位
    java interface 强制类型转换小记
    android 修改系统程序图标大小
    git 合并patch的方法
  • 原文地址:https://www.cnblogs.com/wenbao/p/6421041.html
Copyright © 2011-2022 走看看