给定范围内数组的两个元素之间的最大差异

时间:2017-07-21 11:46:53

标签: algorithm data-structures segment-tree

我需要有效地找到max {S},使得在给定范围[i,j]中S =(A [i] -A [j])。我无法找到除强力解决方案之外的解决方案,其中每个查询都将数组从索引i迭代到索引j并找到解决方案。我正在考虑使用两个段树1来寻找最小值而另一个用于在给定范围内找到最大值但是因为存在额外的约束使得i <= j所以这在每种情况下都不会给出正确的答案。

Constraint:i<=j
n- number of elements in an array (n<=10^6) 
q- number of Queries (q<=10^5)


Example:

Input
5
2 8 4 9 7
2
0 4
2 4

Output
4
2

Explanation:
Input consists of an array with 5 elements and then 2 queries.
1) In the range [0,4] - (8-4) = 4 is the answer
2) In the range [2,4] - (9-7) = 2 is the answer

1 个答案:

答案 0 :(得分:0)

这个问题对我来说似乎很有意思,现在我不知道我的方法是否完全正确,但是我试了一下它给了我当前输入的正确结果。

因此,根据我的方法,我保留一个分段树以保持所有范围的最大值,并保留另一个分段树,其存储左侧最大值 - 右侧最大值之间的差值。

这里需要注意的是,为什么我这样做是因为我们需要A [i] - A [j]和i&lt; = j,所以如果我们继续存储最大左范围 - 最大的右范围,那么我们总是会得到差值而且i <= j。

查看我的代码,了解更多信息。

    #include <bits/stdc++.h>

    using namespace std;

    const int N = 1e5;  // limit for array size
    int n;  // array size
    int t[2 * N];
    int t_ans[2*N];

    void build1() {  // build the tree
      for (int i = n - 1; i > 0; --i) t[i] = max(t[i<<1],t[i<<1|1]);
    }

    void build2() {  // build the tree
      for (int i = n - 1; i > 0; --i) t_ans[i] = t[i<<1] - t[i<<1|1];
    }

    void modify(int p, int value) {  // set value at position p
      for (t[p += n] = value; p > 1; p >>= 1) t[p>>1] = t[p] + t[p^1];
    }

    int query(int l, int r) {  // sum on interval [l, r)
      int res = 0;
      for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
        if (l&1) res = max(res,t[l++]);
        if (r&1) res = max(res,t[--r]);
      }
      return res;
    }

    int query2(int l, int r) {  // sum on interval [l, r)
      int res = 0;
      for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
        if (l&1) res = max(res, t_ans[l++]);
        if (r&1) res = max(res, t_ans[--r]);
      }
      return res;
    }

    int main() {
      cin>>n;
      for (int i = 0; i < n; ++i) {
        scanf("%d", t + n + i);
      }
      build1();
      build2();

      /*
      For testing purpose only
      for(int i=0; i<2*n; i++) {
        cout<<t[i]<<" ";
      }
      cout<<endl;
      for(int i=0; i<2*n; i++) {
        cout<<t_ans[i]<<" ";
      }
      cout<<endl;
      */
      int q;
      cin>>q;
      for(int i=0; i<q; i++) {
        int l,r;
        cin>>l>>r;
        cout<<query2(l,r+1)<<endl;
      }

      return 0;
    }

我保留两个分段树,一个用于存储最大范围值的树,它被称为t,另一个用于存储差异的最大值,并且存储在t_ans中。

现在我调用两种不同的构建方法,build1()构建最大值的段树,build2()构建段树,以获得左树的最大值 - 右树的最大值之间的差异。

如果我在当前的方法中犯了任何错误或错误,请告诉我。

希望这有帮助!