选定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;
}