关于OI-wiki
  • 板块学术版
  • 楼主JK_LOVER
  • 当前回复26
  • 已保存回复26
  • 发布时间2020/9/22 16:58
  • 上次更新2023/11/5 12:47:38
查看原帖
关于OI-wiki
227824
JK_LOVER楼主2020/9/22 16:58

这个是 oiwikioi-wiki 的笛卡尔树例题讲解中的建树,个人感觉是 O(nlogn)O(n\log n) ,为什么文中却说:用每一个点计算出来的值更新答案即可。显然这个可以一次 DFS 完成,因此复杂度仍是 O(n)O(n) 的。那么请问我是哪里理解错了?

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 100000 + 10, INF = 0x3f3f3f3f;

struct node {
  int idx, val, par, ch[2];
  friend bool operator<(node a, node b) { return a.idx < b.idx; }
  void init(int _idx, int _val, int _par) {
    idx = _idx, val = _val, par = _par, ch[0] = ch[1] = 0;
  }
} tree[N];

int root, top, stk[N];
ll ans;
int cartesian_build(int n) {
  for (int i = 1; i <= n; i++) {
    int k = i - 1;
    while (tree[k].val > tree[i].val) k = tree[k].par;
    tree[i].ch[0] = tree[k].ch[1];
    tree[k].ch[1] = i;
    tree[i].par = k;
    tree[tree[i].ch[0]].par = i;
  }
  return tree[0].ch[1];
}
int dfs(int x) {
  if (!x) return 0;
  int sz = dfs(tree[x].ch[0]);
  sz += dfs(tree[x].ch[1]);
  ans = max(ans, (ll)(sz + 1) * tree[x].val);
  return sz + 1;
}
int main() {
  int n, hi;
  while (scanf("%d", &n), n) {
    tree[0].init(0, 0, 0);
    for (int i = 1; i <= n; i++) {
      scanf("%d", &hi);
      tree[i].init(i, hi, 0);
    }
    root = cartesian_build(n);
    ans = 0;
    dfs(root);
    printf("%lld\n", ans);
  }
  return 0;
}
2020/9/22 16:58
加载中...