鉛 單調棧例題

關於學習

看洛谷網校學習的安全

單調棧例題

例題:學習

  • [x] P2947 [USACO09MAR]向右看齊Look Up
  • [x] POJ3250 Bad Hair Day
  • [x] POJ2796Feel Good
  • [x] POJ2559Largest Rectangle in a Histogram
  • [x] BZOJ 1345: [Baltic2007]序列問題Sequence
  • [x] BZOJ4750: 密碼安全
  • [x] BZOJ3039: 玉蟾宮
  • [ ] 【uoj#213】[UNR #1]爭奪聖盃

Solution:

T1:向右看齊Look Up 單調棧裸題
T2:POJ3250 Bad Hair Day 單調棧裸題
T3:考慮第i位爲最小值來更新答案,用單調棧維護出左邊第一個大於他的位置,和右邊第一個大於他的位置便可。
T4:先貪心考慮以第i個矩形爲基礎的矩形有多大,而後用單調棧維護便可。
T5:在最優策略下,非最大值的數,必定是與它左右第一個比它大的數中較小的那個替代的。
T6:考慮第i位是最小值,而後二進制拆位計算方案數。
T7:考慮枚舉每一點,而後每一點橫向能擴展到哪裏,而後跟T4差很少了
T8:不會
把一些難寫的題放上來吧。spa

BZOJ 1345: [Baltic2007]序列問題Sequence

int a[maxN], b[maxN], c[maxN];
int sta[maxN] , top;

int main() {
    int n = gi();
    a[0] = INF;a[n + 1] = INF;
    for(int i = 1;i <= n;++ i) a[i] = gi();
    for(int i = n;i >= 1;-- i) {
        while(top && a[sta[top]] < a[i]) {
            b[sta[top --]] = i;
        }
        sta[++ top] = i;
    }
    for(int i = 1;i <= n;++ i) {
        while(top && a[sta[top]] <= a[i]) {
            c[sta[top --]] = i;
        }
        sta[++ top] = i;
    }
    ll ans = 0;
    for(int i = 1;i <= n;++ i) {
        int x = min(a[b[i]] , a[c[i]]);
        if(x != INF) ans += x;
    }
    printf("%lld",ans);
    return 0;
}
int a[maxN], b[maxN], c[maxN];
int sta[maxN] , top;

int main() {
    int n = gi();
    a[0] = INF;a[n + 1] = INF;
    for(int i = 1;i <= n;++ i) a[i] = gi();
    for(int i = n;i >= 1;-- i) {
        while(top && a[sta[top]] < a[i]) {
            b[sta[top --]] = i;
        }
        sta[++ top] = i;
    }
    top = 0;
    for(int i = 1;i <= n;++ i) {
        while(top && a[sta[top]] <= a[i]) {
            c[sta[top --]] = i;
        }
        sta[++ top] = i;
    }
    ll ans = 0;
    for(int i = 1;i <= n;++ i) {
        int x = min(a[b[i]] , a[c[i]]);
        if(x != INF) ans += x;
    }
    printf("%lld",ans);
    return 0;
}

BZOJ4750: 密碼安全

int a[N] , sum[N] , c[N][30] , lp[N] , rp[N] , sta[N] , tot;
int main() {
    int T;
    scanf("%d" , &T);
    while(T -- ) {
        int n , i , j , ans = 0;
        scanf("%d" , &n);
        memset(c , 0 , sizeof(c));
        for(i = 2 ; i <= n + 1 ; i ++ ) {
            scanf("%d" , &a[i]) , sum[i] = sum[i - 1] ^ a[i];
            for(j = 0 ; j < 30 ; j ++ ) c[i][j] = c[i - 1][j] + (bool)(sum[i] & (1 << j));
        }
        tot = 0 , sta[0] = 1;
        for(i = 2 ; i <= n + 1 ; i ++ ) {
            while(tot && a[sta[tot]] < a[i]) tot -- ;
            lp[i] = sta[tot] , sta[++ tot] = i;
        }
        tot = 0 , sta[0] = n + 2;
        for(i = n + 1 ; i >= 2 ; i -- ) {
            while(tot && a[sta[tot]] <= a[i]) tot -- ;
            rp[i] = sta[tot] , sta[++tot] = i;
        }
        for(i = 2 ; i <= n + 1 ; i ++ )
            for(j = 0 ; j < 30 ; j ++ )
                ans = (ans + ((ll)(c[i - 1][j] - c[lp[i] - 1][j]) * (rp[i] - i - c[rp[i] - 1][j] + c[i - 1][j])
                           + (ll)(i - lp[i] - c[i - 1][j] + c[lp[i] - 1][j]) * (c[rp[i] - 1][j] - c[i - 1][j])) % mod
                           * (1 << j) % mod * a[i]) % mod;
        printf("%d\n" , ans);
    }
    return 0;
}

Largest Rectangle in a Histogramcode

BZOJ3039: 玉蟾宮

using namespace std;
int a[N][N] , sta[N] , tot , lp[N] , rp[N];
char str[5];
int main() {
    int n , m , i , j , ans = 0;
    scanf("%d%d" , &n , &m);
    for(i = 1 ; i <= n ; i ++ ) {
        for(j = 1 ; j <= m ; j ++ ) {
            scanf("%s" , str);
            if(str[0] == 'F')
                a[i][j] = a[i - 1][j] + 1;
        }
        tot = 0 , sta[0] = 0;
        for(j = 1 ; j <= m ; j ++ ) {
            while(tot && a[i][j] <= a[i][sta[tot]]) tot -- ;
            lp[j] = sta[tot] , sta[++tot] = j;
        }
        tot = 0 , sta[tot] = m + 1;
        for(j = m ; j ; j -- ) {
            while(tot && a[i][j] <= a[i][sta[tot]]) tot -- ;
            rp[j] = sta[tot] , sta[++tot] = j;
        }
        for(j = 1 ; j <= m ; j ++ ) ans = max(ans , a[i][j] * (rp[j] - lp[j] - 1));
    }
    printf("%d\n" , ans * 3);
    return 0;
}
相關文章
相關標籤/搜索