TLE on 17,悬 2 关!
查看原帖
TLE on 17,悬 2 关!
726139
残阳如血楼主2024/7/17 16:21
#include <bits/stdc++.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
using pii = std::pair<int, int>;
const int N = 1e6 + 10;
// const int N = 11;
const int INF = 2e9;

int n, m, q, w[N];
std::multiset<int> set[N];
std::vector<int> g[N], bcc[N];

namespace LCT { // 树链剖分
  int tot, fa[N], dep[N], siz[N], son[N], top[N], dfn[N], rnk[N];

  void dfs1(int u, int f) {
    fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1;
    for (auto v : bcc[u]) {
      if (v == f) continue;
      dfs1(v, u);
      siz[u] += siz[v];
      if (siz[son[u]] < siz[v]) son[u] = v;
    }
  }

  void dfs2(int u, int ftop) {
    dfn[u] = ++tot, rnk[tot] = u, top[u] = ftop;
    if (son[u]) dfs2(son[u], ftop);
    for (auto v : bcc[u])
      if (v ^ fa[u] && v ^ son[u]) dfs2(v, v);
  }

  void work() {
    dfs1(1, 0);
    dfs2(1, 0);
  }
}

namespace Tarjan { // Tarjan 缩点
  // std::stack<int> stk;
  int stk[N], top;
  int cnt, tot, dfn[N], low[N];

  void add(int cnt, int u) {
    bcc[cnt].push_back(u);
    bcc[u].push_back(cnt);
  }

  void record(int u, int v) {
    add(tot, u);
    while (stk[top] != v)
      add(tot, stk[top--]);
    add(tot, stk[top--]);
  }

  void solve(int u, int fa) {
    dfn[u] = low[u] = ++cnt;
    stk[++top] = u;
    for (auto v : g[u]) {
      if (v == fa) continue;
      if (!dfn[v]) {
        solve(v, u), low[u] = min(low[u], low[v]);
        if (low[v] >= dfn[u]) ++tot, record(u, v);
      } else low[u] = min(low[u], dfn[v]);
    }
  }

  void work() {
    tot = n;
    solve(1, 0);
  }
}

namespace SegmentTree {
  int a[4 * N];

  void pushup(int u) {
    a[u] = min(a[u * 2], a[u * 2 + 1]);
  }

  bool outRange(int l, int r, int L, int R) {
    return L > r || R < l;
  }

  bool inRange(int l, int r, int L, int R) {
    return l >= L && r <= R;
  }

  void build(int u, int l, int r) {
    if (l == r) {
      a[u] = w[LCT::rnk[l]];
      return ;
    }
    int mid = l + r >> 1;
    build(u * 2, l, mid);
    build(u * 2 + 1, mid + 1, r);
    pushup(u);
  }

  int query(int u, int l, int r, int L, int R) {
    // 查询 [L,R] 内的最小值
    if (outRange(l, r, L, R)) return INF;
    if (inRange(l, r, L, R)) return a[u];
    int mid = l + r >> 1;
    return min(query(u * 2, l, mid, L, R),
               query(u * 2 + 1, mid + 1, r, L, R));
  }

  void update(int u, int l, int r, int p, int x) {
    // 将 p 点赋为 x
    if (outRange(l, r, p, p)) return ;
    if (inRange(l, r, p, p)) {
      a[u] = x;
      return ;
    }
    int mid = l + r >> 1;
    update(u * 2, l, mid, p, x);
    update(u * 2 + 1, mid + 1, r, p, x);
    pushup(u);
  }
}

void input() {
  scanf("%d%d%d", &n, &m, &q);
  for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
  for (int i = 1, u, v; i <= m; ++i) {
    scanf("%d%d", &u, &v);
    g[u].push_back(v);
    g[v].push_back(u);
  }
}

void init() {
  Tarjan::work();
  LCT::work();
  for (int i = 1; i <= n; ++i)
    if (LCT::fa[i]) set[LCT::fa[i]].insert(w[i]);
  for (int i = n + 1; i <= Tarjan::tot; ++i)
    w[i] = *set[i].begin();
  SegmentTree::build(1, 1, Tarjan::tot);
}

void work1(int p, int x) {
  SegmentTree::update(1, 1, Tarjan::tot, LCT::dfn[p], x);
  if (LCT::fa[p]) {
    int f = LCT::fa[p];
    set[f].erase(set[f].lower_bound(w[p]));
    set[f].insert(x);
    if (w[f] != *set[f].begin()) {
      w[f] = *set[f].begin();
      SegmentTree::update(1, 1, Tarjan::tot, LCT::dfn[f], w[f]);
    }
  }
  w[p] = x;
}

void work2(int x, int y) {
  int ans = INF;
  while (LCT::top[x] != LCT::top[y]) {
    if (LCT::dep[LCT::top[x]] < LCT::dep[LCT::top[y]])
      std::swap(x, y);
    ans = min(ans, SegmentTree::query(1, 1, Tarjan::tot, LCT::dfn[LCT::top[x]], LCT::dfn[x]));
    x = LCT::fa[LCT::top[x]];
  }
  if (LCT::dfn[x] > LCT::dfn[y]) std::swap(x, y);
  ans = min(ans, SegmentTree::query(1, 1, Tarjan::tot, LCT::dfn[x], LCT::dfn[y]));
  if (x > n) ans = min(ans, w[LCT::fa[x]]);
  printf("%d\n", ans);
}

void solve() {
  init();
  char op;
  for (int a, b; q; --q) {
    getchar();
    scanf("%c%d%d", &op, &a, &b);
    if (op == 'C') work1(a, b);
    else if (op == 'A') work2(a, b);
    else exit(1);
  }
}

signed main() {
//   freopen("uoj1.in", "r", stdin);
//   freopen("uoj1.out", "w", stdout);
  input();
  solve();
  return 0;
}
2024/7/17 16:21
加载中...