Lightoj1083 Histogram(線斷樹+二分)

選定a[i]是,以它的高爲準,往左找第一個小於它的後一個位置,往右找第一個小於它的前一個位置。

const int maxn = 3e4 + 123;
int a[maxn];
int n;
struct SegmentTree {
    struct node {
        int l, r, _min;
    }p[maxn<<2];
    void build(int rt,int l, int r) {
        p[rt] = node{l, r, INF};
        if (l == r) {
            scanf("%d", &p[rt]._min);
            a[l] = p[rt]._min;
            return ;
        }
        int mid = (l + r) >> 1;
        build(lson, l, mid), build(rson, mid + 1, r);
        p[rt]._min = min(p[lson]._min, p[rson]._min);
    }
    int Query(int rt,int L, int R) {
        if (L <= p[rt].l && p[rt].r <= R) return p[rt]._min;
        int mid = (p[rt].l + p[rt].r) >> 1;
        int res = INF;
        if (L <= mid) res = min(res, Query(lson, L, R));
        if (R > mid && p[rson]._min < res) res = min(res, Query(rson, L, R));
        return res;
    }
}solve;
int find_l(int x, int p) {
    int l = 1, r = p;
    int ans = 0;
    while(l <= r) {
        int mid = (l + r) >> 1;
        int _min = solve.Query(1, mid, p);
        if (_min >= x) {
            r = mid - 1;
            ans = mid;
        }else l = mid + 1;
    }
    return ans;
}
int find_r(int x, int p) {
    int l = p, r = n;
    int ans = 0;
    while(l <= r) {
        int mid = (l + r) >> 1;
        int _min = solve.Query(1, p, mid);
        if (_min >= x) {
            l = mid + 1;
            ans = mid;
        }else r = mid - 1;
    }
    return ans;
}
int main(int argc, const char * argv[])
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);

    int kase;read(kase);
    while(kase--) {
        read(n);
        solve.build(1, 1, n);
        LL sq = 0;
        for (int i = 1;i <= n;++i) {
            int l = find_l(a[i], i);
            int r = find_r(a[i], i);
            sq = max(sq, 1LL * a[i] * (r - l + 1));
        }
        printf("Case %d: %lld\n", ++nCase, sq);
    }

    // showtime;
    return 0;
}
發佈了304 篇原創文章 · 獲贊 7 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章