poj2796
阅读原文时间:2023年07月10日阅读:1

#include
/*
* source poj.2796
* 题目: 
* 给定一个非负数的数组 其中value[l,r] = sum(l,r) * min (l,r);
*   求 最大值和,最大值的位置
* 题解:
* 所求的区域的最小值是x的话一定是这个值向左右去延伸至比他大的元素为止
*   而这个问题的求解一般是n^2的问题,但是我们不能接受因此;
* 维护这个区间需要我们维护一个stack
* 具体操作如下
* (1)元素入栈
*    1,记录值(value, weight) -> weight 初始是1,value是入栈的值,
*     2,先让大于等于value的值出栈,并且更新 ANS [value * weight]  对比决定是否更新.   
*     3,如果这个栈顶元素也大于等于value, 把出栈的这个值的重量给目前的栈顶元素, 到步骤(2),否则到步骤(4).
*    4,把这个出栈的重量给 准备入栈的元素.
*     5,元素入栈
*   (2)元素全部入栈后 因为还有元素在里面. 剩下的元素逐个出栈,  只不过把这个元素的重量给下一个栈顶元素. 类似与插入-1.
* hint:
*
*     其实他每次出栈的 就是我们刚开说的那种区间, 以那个元素为做小值向左右扩展得到的区间值.
*
*     对于栈顶元素.
*       一个元素的入栈 会促使 左侧比他大的合并,
* 而后出栈的时候右侧肯定也都合并到自己身上,因此栈顶元素对于我们所扫描到的位置一定是合法的
*      栈顶元素肯定向右或者说向左都是达标的;
*      这是个斜率优化问题. 怀念以前,现在是个弱鸡(ง •̀_•́)ง
*/
#define min(x, y) ( (x) < (y) ? (x) : (y) ) #define max(x, y) ( (x) < (y) ? (y) : (x) ) const int N = 1e5; struct Ans { int l, r; long long value; Ans(){l = r = value = -;} bool operator < (const Ans & rht ) const { return value < rht.value; } void out(){ printf("%lld\n%d %d\n", value, l, r); } void show(int i) { printf("i = %d %d %d %lld \n", i, l, r, value); } }; struct Info { long long h, w; int p; Info(){} Info(long long _h, long long _w, int _p):h(_h), w(_w), p(_p) {} bool operator < (const Info & rht) const { return this -> h < rht.h; } Info operator + (const Info & rht) const { return Info( min(rht.h, this -> h), rht.w + this -> w, this -> p);
}
};
Info stack[N + ];
int pos;
Ans ans;
inline void init() {
pos = ;
ans = Ans();
}
void in(long long tmp, int i) {
Info inStack = Info(tmp, tmp, i);
Info key = Info(0x7fffffff, , -);
while(pos != && stack[pos - ].h >= inStack.h) {
key = stack[--pos] + key;
Ans wps = Ans();
wps.l = key.p;
wps.r = i - ;
wps.value = (long long )key.w * (long long )key.h;

    ans = max(ans, wps);  
}  
if (key.p != -) {  
    inStack = key + inStack;  
}  
stack\[pos++\] = inStack;  

}
int main() {
int n;
long long tmp;
while(~scanf("%d", &n)) {
init();
for(int i = ; i <= n; ++i) {
scanf("%lld", &tmp);
in(tmp, i);
}
in(, n + );
ans.out();
}
return ;
}