计算具有条件的子数组?

时间:2015-08-11 19:13:57

标签: arrays algorithm math dynamic-programming

我有一个N个整数和M对的数组(a,b) - > a,b是数组的索引。

我必须计算具有N个元素的数组A的非空连续子序列(子分段)的数量,使得没有分段包括任何M对的两个元素(简单地说,减去具有任何两个元素的分段的数量)来自总分段的M对)?

示例:

 N=5 , M=1 -> pair (1,4) then ans=13 .
 {(1),(2),(3),(4),(5),(1,2),(2,3),(3,4),(4,5),(1,3),(2,4),(3,5),(2,5)}

我尝试过的解决方案:我试图应用动态编程但没有通过它,然后试着想贪婪然后也没有得到它。

1 个答案:

答案 0 :(得分:1)

这是O(n + m)解决方案。

对于每个索引 i ,我们将在左侧找到第一个索引 j ,这样我们就无法在 j 上启动段或更早,并以 i 或更进一步结束。如果我们有这些索引,我们可以通过为每个索引添加 i - left [i] 来轻松实现我们的答案。

如何找到它?

首先,使所有 first [i] 等于0。 然后读取所有对(a,b)(假设 a< = b )并使 left [b] 等于 max(左[b],a)

在此之后让我们使用动态编程。从左到右为每个索引 i> 1,left [i] = max(left [i],left [i - 1])

#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1000000;
int n, m;
int LEFT[MAXN + 5];

int main() {
    ios_base::sync_with_stdio(0);

    cin >> n >> m;

    for(int i = 1; i <= n; i++)
        LEFT[i] = 0;

    for(int i = 1; i <= m; i++) {
        int a, b;
        cin >> a >> b;
        if(a > b) swap(a, b);
        LEFT[b] = max(LEFT[b], a);
    }

    long long answer = 0;
    for(int i = 2; i <= n; i++)
        LEFT[i] = max(LEFT[i], LEFT[i - 1]);
    for(int i = 1; i <= n; i++)
        answer += i - LEFT[i];
    cout << answer << endl;
}