MLE 45 分 求助

P4513 小白逛公园

残阳如血 @ 2024-05-09 21:15:41

// 单点修改,区间查询
#include <iostream>
#include <algorithm>
const int N = 5e5 + 10;
const int INF = -2e9;
typedef long long lint;

struct TreeNode {
  int l, r; // 区间为 [l,r]
  lint sum, ans, lmax, rmax;
  // sum:区间总和,ans:区间最大子段和,lmax:最大前缀,rmax:最大后缀
  TreeNode *lson, *rson;
  TreeNode(lint _sum = INF, lint _ans = INF, lint _lamx = INF, lint _rmax = INF, int _l = -1, int _r = -1, TreeNode *_lson = nullptr, TreeNode *_rson = nullptr)
  : l(_l), r(_r), sum(_sum), ans(_ans), lmax(_lamx), rmax(_rmax), lson(_lson), rson(_rson) {}
  ~TreeNode() {
    if (lson) delete lson;
    if (rson) delete rson;
    lson = rson = nullptr;
  }
};

int n, m, a[N];

bool inRange(TreeNode *u, int L, int R) { // 判断 [u->l,u->r] 是否被 [L,R] 完全包含
  return u->l >= L && u->r <= R;
}

bool outRange(TreeNode *u, int L, int R) { // 判断 [u->l,u->r] 是否与 [L,R] 完全无交
  return u->l > R || u->r < L;
}

void pushup(TreeNode *u, TreeNode *ls, TreeNode *rs) {
  u->sum = ls->sum + rs->sum;
  u->lmax = std::max(ls->lmax, ls->sum + rs->lmax);
  u->rmax = std::max(rs->rmax, rs->sum + ls->rmax);
  u->ans = std::max({ls->ans, rs->ans, ls->rmax + rs->lmax});
}

TreeNode *build(int l, int r) { // 建树
  TreeNode *u = new TreeNode;
  u->l = l, u->r = r;
  if (l == r) {
    u->sum = u->ans = u->lmax = u->rmax = a[l]; // 单个的所有值均为自身
    u->lson = u->rson = nullptr;
    return u;
  }
  int mid = l + r >> 1;
  u->lson = build(l, mid); // 左子树 [l,mid]
  u->rson = build(mid + 1, r); // 右子树 [mid + 1, r]
  pushup(u, u->lson, u->rson);
  return u;
}

TreeNode *query(TreeNode *u, int L, int R) {
  if (outRange(u, L, R)) return new TreeNode; // 默认 ans=INF 的值
  if (inRange(u, L, R)) return u;
  TreeNode *res = new TreeNode;
  pushup(res, query(u->lson, L, R), query(u->rson, L, R)); // 合并左右两棵子树查询得到的值
  return res;
}

void update(TreeNode *u, int p, int x) {
  if (u->l == u->r) {
    u->sum = u->ans = u->lmax = u->rmax = x;
    return ;
  }
  int mid = u->l + u->r >> 1;
  if (p <= mid) update(u->lson, p, x);
  else update(u->rson, p, x);
  pushup(u, u->lson, u->rson);
}

int main() {
  // freopen("sample.in", "r", stdin);
  // freopen("Std3.out", "w", stdout);
  std::cin.tie(0)->sync_with_stdio(0);
  std::cin >> n >> m;
  for (int i = 1; i <= n; ++i) std::cin >> a[i];
  TreeNode *root = build(1, n);
  for (int k, a, b; m; --m) {
    std::cin >> k >> a >> b;
    int s = std::min(a, b), t = std::max(a, b);
    if (k == 1) std::cout << query(root, s, t)->ans << '\n';
    else update(root, a, b);
  }
  std::cout.flush();
  return 0;
}

记录详情 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)


by 残阳如血 @ 2024-05-10 17:14:27

如果查询小区间,线段树每一层大概率会 new 一次,然后 new 了没释放,所以 new\log 次导致空间复杂度变成 n\log n。开个内存池就可以过了


|