【问题标题】:Looking for a data structure to perform range element update efficiently寻找一种数据结构来有效地执行范围元素更新
【发布时间】:2017-08-07 03:14:41
【问题描述】:

我目前有以下数据结构:

class DataStructure {
public:
  DataStructure(int n) : m_data(n, 0) {
  }

  void update(int i, int j, int value) {
    for (int k = i; k <= j; ++k) {
      m_data[k] = max(m_data[k], value);
    }
  }

  void reset(int i) {
    m_data[i] = 0;
  }

  int query(int i) {
    return m_data[i];
  }

private:
  vector<int> m_data;
};

所以它的作用相当简单:

  • 最初有一个由 n 个整数组成的向量,初始化为零。
  • update(i, j, value) 将 [i, j] 范围内的元素更新为给定值及其各自当前值的最大值。给定的值在 [0, n] 的范围内。
  • reset(i) 将索引 i 处的值重置为 0。
  • query(i) 返回索引 i 处的值。

我需要执行 n 次更新、n 次重置和 n 次查询操作。目前此代码需要 O(n*n) 时间,因为更新操作通常是 O(n)。

我想知道是否有一些聪明的方法可以将 n 次更新、n 次重置和 n 次查询操作的时间改进为 O(n*log n) 时间(或更好),同时保持 O(n) 空间复杂度?

【问题讨论】:

  • 第2点不清楚,是否会在{A[L]...A[R]}中将[L,R]中的所有值都更新到最大值?
  • @marvel308 读取代码中的更新函数......似乎应该在单个元素的基础上完成
  • 您需要在线算法还是提前知道所有查询?
  • 我认为这可以通过分段树以及惰性传播数据结构来完成
  • 如果您像 DAle 那样事先不知道所有查询,那么在最坏的情况下,您实际上需要执行 n² 次更新——在这种情况下,您的更新以update(0, n-1, 1), update(0, n-1, 2), update(0, n-1, 3), ..., update(0, n-1, n) 给出。所以不可能在小于 O(n²) 的时间内完成。

标签: algorithm data-structures language-agnostic


【解决方案1】:

感谢@qwertman 的解释,这里的算法应该可以工作

#include <iostream>
#include <cstdio>
using namespace std;
#define max(a, b) (a>b?a:b)
int tree[100005], lazy[100005];
void init(int idx, int l, int r){
    if(l>r)
        return ;
    if(l==r){
        tree[idx] = 0;
        lazy[idx] = -1;
    }
    else {
        tree[idx] = 0;
        lazy[idx] = -1;
        int mid = (l+r)/2;
        init(2*idx, l, mid);
        init(2*idx+1, mid+1, r);
    }
}
// l and r is for internal use the range a-b has to be updated
void update(int idx, int l, int r, int a, int b, int val, bool isReset){
    if(l>r || b<l || a>r){
        return;
    }
    // printf("idx=%d l=%d r=%d a=%d b=%d val=%d\n",idx,l,r,a,b,val);
    if(lazy[idx] != -1){
        tree[idx] = max(tree[idx], lazy[idx]);
        lazy[2*idx] = max(lazy[2*idx], lazy[idx]);
        lazy[2*idx+1] = max(lazy[2*idx+1], lazy[idx]);
        lazy[idx] = -1;
    }
    if(l>=a && r<=b){
        // printf("updating\n");
        tree[idx] = max(tree[idx], val);
        if(isReset){
            tree[idx] = val;
        }
        lazy[2*idx] = max(lazy[2*idx], val);
        lazy[2*idx+1] = max(lazy[2*idx+1], val);
        lazy[idx] = -1;
    }
    else {
        int mid = (l+r)/2;
        update(2*idx, l, mid, a, b, val, isReset);
        update(2*idx+1, mid+1, r, a, b, val, isReset);
        tree[idx] = max(tree[2*idx], tree[2*idx+1]);
    }
}
int query(int idx, int l, int r, int a){
    if(l>r || a<l || a>r){
        return -1;
    }
    // printf("idx=%d l=%d r=%d a=%d\n",idx,l,r,a);
    if(lazy[idx] != -1){
        tree[idx] = max(tree[idx], lazy[idx]);
        lazy[2*idx] = max(lazy[2*idx], lazy[idx]);
        lazy[2*idx+1] = max(lazy[2*idx+1], lazy[idx]);
        lazy[idx] = -1;
    }
    if(l==a && r==a){
        // printf("----l=%d r=%d a=%d tree=%d\n",l,r,a,tree[idx]);
        return tree[idx];
    }
    else {
        int mid = (l+r)/2;
        int left = query(2*idx, l, mid, a);
        int right = query(2*idx+1, mid+1, r, a);
        return max(left, right);
    }
}
int main() {
    // initializing everything to 0 
    init(1, 1, 10);

    // updating range 1-4 with value 7
    update(1, 1, 10, 1, 4, 7, false);

    // query for 3 should result in 7
    cout << query(1, 1, 10, 3) << endl;

    // updating 3-3 with value 9
    update(1, 1, 10, 3, 3, 9, false);

    // should give 9
    cout << query(1, 1, 10, 3) << endl;

    // isReset is set to true, so the function will do a hard reset
    update(1, 1, 10, 3, 3, 0, true);

    // should give 0
    cout << query(1, 1, 10, 3) << endl;
    return 0;
}

您可以在http://ideone.com/Mkp4dQ 运行此代码
一些有用的链接,用于学习延迟传播的段树
hackerearth Geeksforgeeks

【讨论】:

  • 看起来很有趣!等我回去工作时,我会详细阅读。
  • 它应该可以工作,因为我总是将 tree[idx] 更新为孩子的最大值,但是是的,我们只关心叶子中的值,所以无论如何它都可以解决这个问题跨度>
猜你喜欢
  • 1970-01-01
  • 2011-09-21
  • 2023-01-19
  • 2015-07-16
  • 1970-01-01
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多