第一次接触单调栈是暑假的时候,那时做到了了 HDU上的一题 : Largest Rectangle in a Histogram
后来在范总的帮助下敲掉了。
今天决定重新坐下这类题,目的是完善下代码风格和熟悉下。
题目都是蛮简单的,核心算法就是用单调栈处理出第i个点左右最长可以延伸到的位置(记做 : L[i] 和 R[i])。
挂了三道POJ题目 :
1 Terrible Sets : (题意有点坑而已,理解后会发现和HDU上那题是一样的)
2 Feel Good : (首先O(n)预处理出任意区间和,然后注意下会超int需要用__int64来保存区间和和最后的答案)
3 Sticks Problem: (单调栈预处理后,我是用O(n^2)寻找最后的答案的,如果从R[i] 的最右端找过来,虽然看似O(n^2),但是如果符合要求直接break的话还是可以过的)
最后贴一个单调栈预处理的代码 :
void init()
{
sta[0] = 0; cnt = 0;
for (int i = 1;i <= n;i++)
{
if (a[i] >= sta[cnt])
{
sta[++cnt] = a[i];
tot[cnt] = i;
}
else
{
while (a[i] < sta[cnt])
{
R[tot[cnt]] = i - 1;
cnt--;
}
sta[++cnt] = a[i];
tot[cnt] = i;
}
}
for (int i = 1;i <= cnt;i++)R[tot[i]] = n;
sta[0] = 0; cnt = 0;
for (int i = n;i >= 1;i--)
{
if (a[i] >= sta[cnt])
{
sta[++cnt] = a[i];
tot[cnt] = i;
}
else
{
while (a[i] < sta[cnt])
{
L[tot[cnt]] = i + 1;
cnt--;
}
sta[++cnt] = a[i];
tot[cnt] = i;
}
}
for (int i = 1;i <= cnt;i++)L[tot[i]] = 1;
}