所有段中所有最大值和最小值的总和

时间:2012-12-03 11:24:41

标签: c++ algorithm optimization segments

我正在做一个问题,需要找到一个段中最大元素的总和 - 一个段中最小元素的总和。我尝试使用稀疏表,但它是两个缓慢的时间限制。所以我做了这样的事情:

如果n=4段为[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]。 问题类似于RMQ问题,但我必须为所有段执行此操作并找到

sum=max(a[1],a[2])+ max(a[1],a[2],a[3])+max(a[1],a[2],a[3],a[4])+max(a[2],a[3])+m‌​ax(a[2],a[3],a[4])+max(a[3],a[4])-min(a[1],a[2])+min(a[1],a[2],a[3])+min(a[1],a[2‌​],a[3],a[4])+min(a[2],a[3])+min(a[2],a[3],a[4])+min(a[3],a[4])

for(i=1;i<n;i++)
{
    maxtilli[i-1]=INT_MIN;
    mintilli[i-1]=INT_MAX;
    for(k=1,j=i;j<=n;k++,j++)
    {
        if(a[j]>maxtilli[k-1])
        {
            maxtilli[k]=a[j];
        }
        else
        {
             maxtilli[k]=maxtilli[k-1];
        }

        if(a[j]<mintilli[k-1])
        {
            mintilli[k]=a[j];
        }
        else
        {   
            mintilli[k]=mintilli[k-1];
        }
        if(i!=j)
        { 
            ans+=(maxtilli[k]-mintilli[k]);
        }
    }
}

此处n大约为100,000。那么有什么方法可以优化它。

假设n=4,则细分为[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]

所需要的是 sum=max(a[1],a[2])+max(a[1],a[2],a[3])+max(a[1],a[2],a[3],a[4])+max(a[2],a[3])+m‌​ax(a[2],a[3],a[4])+max(a[3],a[4])-min(a[1],a[2])+min(a[1],a[2],a[3])+min(a[1],a[2‌​],a[3],a[4])+min(a[2],a[3])+min(a[2],a[3],a[4])+min(a[3],a[4])

1 个答案:

答案 0 :(得分:0)

我们可以尝试完成第一个问题,即所有细分中最大值的总和。

算法

首先,您可以在整个序列中找到最大值a [i]。将考虑包含[i]的所有段。答案加上A [i] *(i *(n - i))。问题分为两个小序列[1,i - 1]和[i + 1,n],你可以用同样的方式来做。

代码

void cal(int L, int R){
    max_index = find_max(L, R); // O(logN), using Sparse Table or Segment Tree
    int all_segments = (max_index - L + 1) * (R - max_index)
    ans += a[max_index] * all_segments;
    cal(L, max_index - 1);
    cal(max_index + 1, R);
}
// call max_index N times, so the total complexity is O(N * logN)