📌  相关文章
📜  查找具有更新范围的最大产品对的查询

📅  最后修改于: 2021-04-17 12:16:00             🧑  作者: Mango

给定一个由N个正整数组成的数组。任务是根据给定的查询类型执行以下操作。
1.在给定范围内打印最大成对产品。 [LR]
2.用一些给定值更新A i。

例子:

天真的解决方案:蛮力方法是从L遍历到R并检查每对,然后找到其中的最大乘积对。
时间复杂度:每个查询为O(N ^ 2)。

更好的解决方案是遍历然后返回它们的乘积来找到L到R范围内的第一个和第二个最大数字。
时间复杂度:每个查询为O(N)。

一种有效的解决方案是使用段树将最大和第二大数目存储在节点中,然后返回它们的乘积。

下面是上述方法的实现。

// C++ program to find the maximum
// product in a range with updates
#include 
using namespace std;
#define ll long long
  
// structure defined
struct segment {
    // l for largest
    // sl for second largest
    ll l;
    ll sl;
};
  
// function to perform queries
segment query(segment* tree, ll index,
              ll s, ll e, ll qs, ll qe)
{
  
    segment res;
    res.l = -1;
    res.sl = -1;
    // no overlapping case
    if (qs > e || qe < s || s > e) {
  
        return res;
    }
  
    // complete overlap case
    if (s >= qs && e <= qe) {
  
        return tree[index];
    }
  
    // partial overlap case
    ll mid = (s + e) / 2;
  
    // calling left node and right node
    segment left = query(tree, 2 * index,
                         s, mid, qs, qe);
    segment right = query(tree, 2 * index + 1,
                          mid + 1, e, qs, qe);
  
    // largest of ( left.l, right.l)
    ll largest = max(left.l, right.l);
  
    // compute second largest
    // second largest will be minimum
    // of maximum from left and right node
    ll second_largest = min(max(left.l, right.sl),
                            max(right.l, left.sl));
  
    // store largest and
    // second_largest in res
    res.l = largest;
    res.sl = second_largest;
  
    // return the resulting node
    return res;
}
  
// funcntion to update the query
void update(segment* tree, ll index,
            ll s, ll e, ll i, ll val)
{
    // no overlapping case
    if (i < s || i > e) {
        return;
    }
  
    // reached leaf node
  
    if (s == e) {
        tree[index].l = val;
        tree[index].sl = INT_MIN;
        return;
    }
  
    // partial overlap
  
    ll mid = (s + e) / 2;
  
    // left subtree call
    update(tree, 2 * index, s, mid, i, val);
  
    // right subtree call
    update(tree, 2 * index + 1, mid + 1, e, i, val);
  
    // largest of ( left.l, right.l)
    tree[index].l = max(tree[2 * index].l, tree[2 * index + 1].l);
  
    // compute second largest
    // second largest will be
    // minimum of maximum from left and right node
  
    tree[index].sl = min(max(tree[2 * index].l, tree[2 * index + 1].sl),
                         max(tree[2 * index + 1].l, tree[2 * index].sl));
}
  
// Function to build the tree
void buildtree(segment* tree, ll* a, ll index, ll s, ll e)
{
    // tree is build bottom to up
    if (s > e) {
        return;
    }
  
    // leaf node
    if (s == e) {
        tree[index].l = a[s];
        tree[index].sl = INT_MIN;
        return;
    }
  
    ll mid = (s + e) / 2;
  
    // calling the left node
    buildtree(tree, a, 2 * index, s, mid);
  
    // calling the right node
    buildtree(tree, a, 2 * index + 1, mid + 1, e);
  
    // largest of ( left.l, right.l)
    ll largest = max(tree[2 * index].l, tree[2 * index + 1].l);
  
    // compute second largest
    // second largest will be minimum
    // of maximum from left and right node
    ll second_largest = min(max(tree[2 * index].l, tree[2 * index + 1].sl),
                            max(tree[2 * index + 1].l, tree[2 * index].sl));
  
    // storing the largest and
    // second_largest values in the current node
    tree[index].l = largest;
    tree[index].sl = second_largest;
}
  
// Driver Code
int main()
{
  
    // your code goes here
    ll n = 5;
  
    ll a[5] = { 1, 3, 4, 2, 5 };
  
    // allocating memory for segment tree
    segment* tree = new segment[4 * n + 1];
  
    // buildtree(tree, a, index, start, end)
    buildtree(tree, a, 1, 0, n - 1);
  
    // query section
    // storing the resulting node
    segment res = query(tree, 1, 0, n - 1, 0, 2);
  
    cout << "Maximum product in the range "
         << "0 and 2 before update: " << (res.l * res.sl);
  
    // update section
    // update(tree, index, start, end, i, v)
    update(tree, 1, 0, n - 1, 1, 6);
  
    res = query(tree, 1, 0, n - 1, 0, 2);
  
    cout << "\nMaximum product in the range "
         << "0 and 2 after update: " << (res.l * res.sl);
  
    return 0;
}
输出:
Maximum product in the range 0 and 2 before update: 12
Maximum product in the range 0 and 2 after update: 24

时间复杂度:每个查询的O(log N)和用于构建树的O(N)。