良好马蜂 ,高度封装,注释完整,求 debug
查看原帖
良好马蜂 ,高度封装,注释完整,求 debug
356003
Moeebius楼主2023/6/30 20:31

RT,样例第 5、6 行错误

// clang-format off
#include<bits/stdc++.h>
#include <cassert>
using namespace std;

#define il inline
#define mkp make_pair
#define pii pair<int,int>
#define pll pair<long long, long long>
#define fi first
#define se second
#define lll __int128
#define ll long long
#define db double
#define ldb long_double
#define sq(x) ((x)*(x))
#define For(i,j,k) for(int (i)=(j); (i)<=(k); ++(i))
#define ForDown(i,j,k) for(int (i)=(j); (i)>=(k); --(i))
#define pb push_back
#define FileIO(filename) freopen(filename ".in" ,"r",stdin);freopen(filename ".out" ,"w",stdout)
template<typename T> il void read(T &x){ x=0;int f=1;int c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;}
template<typename T, typename ... Args> il void read(T &x, Args &... y){ read(x);read(y...); }
template<typename T> il constexpr T qpow(T x, ll y, T mod=numeric_limits<int>::max()){T ans=1;x%=mod;while(y){if(y&1)(ans*=x)%=mod;(x*=x)%=mod;y>>=1;}return ans;}

#ifndef ONLINE_JUDGE
  #define __lg log2
  namespace _Debug {
		template <typename T> inline void _debug(const char* format, T t) { cerr<<format<<'='<<t<<endl; }
		template <class First, class... Rest> inline void _debug(const char* format, First first, Rest... rest) { while (*format != ',') cerr << *format++; cerr << '=' << first << ","; _debug(format + 1, rest...);}
		template <typename T> ostream& operator<<(ostream& os, const vector<T>& V) { os << "[ "; for (const auto& vv : V) os << vv << ", "; os << "]"; return os; }
    #define debug(...) cerr<<"Line "<<__LINE__<<": ",_debug(#__VA_ARGS__, __VA_ARGS__);
	};
	using namespace _Debug;
#endif

// File head end
// clang-format on

constexpr int MAXN = 1e5 + 5;
int n, Q, cnt = 0, a[MAXN], sz[MAXN], fa[MAXN], dep[MAXN], top[MAXN],
          hson[MAXN], ed[MAXN], id[MAXN], dfn[MAXN], f[MAXN][2], g[MAXN][2];
vector<int> T[MAXN];

struct Matrix { // 矩阵
  int a[2][2], n = 2, m = 2;
  Matrix() { a[0][0] = a[0][1] = a[1][0] = 0, a[1][1] = -1e9; }
  Matrix operator*(const Matrix &rhs) const {
    Matrix res;
    For(i, 0, 1) For(j, 0, 1) For(k, 0, 1) res.a[i][j] =
        max(res.a[i][j], a[i][k] + rhs.a[k][j]);
    return res;
  }
  int &operator[](const pii id) { return a[id.fi][id.se]; } // 下标访问
};
namespace SegmentTree { // 线段树
struct Node {
  int l, r;
  Matrix val;
} T[MAXN << 2];
int segtPtr[MAXN]; // 记录每个点真实编号(非 dfs 序)在线段树里的下标
#define lc(p) ((p) << 1)
#define rc(p) ((p) << 1 | 1)
#define pushUp(p) T[(p)].val = T[lc(p)].val * T[rc(p)].val
il void build(int p, int l, int r) {
  T[p].l = l, T[p].r = r;
  if (l == r) {
    int ptr = dfn[l];
    // cerr << ptr << endl;
    segtPtr[ptr] = p;
    if (!hson[ptr]) { // leaf
      T[p].val[{0, 0}] = f[ptr][0];
      T[p].val[{1, 0}] = f[ptr][1];
    } else { // non-leaf
      T[p].val[{0, 0}] = g[ptr][0];
      T[p].val[{0, 1}] = g[ptr][0];
      T[p].val[{1, 0}] = g[ptr][1];
      T[p].val[{1, 1}] = -1e9;
    }
    return;
  }
  int mid = (l + r) >> 1;
  build(lc(p), l, mid);
  build(rc(p), mid + 1, r);
  pushUp(p);
}
il Matrix qry(int p, int ql, int qr) { // 正常的询问区间「广义」乘
  if (p == 1)
    cerr << dfn[ql] << ' ' << dfn[qr] << endl;
  int l = T[p].l, r = T[p].r;
  if (ql <= l && qr >= r)
    return T[p].val;
  int mid = (l + r) >> 1;
  if (ql <= mid && qr <= mid)
    return qry(lc(p), ql, qr);
  else if (ql > mid && qr > mid)
    return qry(rc(p), ql, qr);
  else if (ql <= mid && qr > mid)
    return qry(lc(p), ql, qr) * qry(rc(p), ql, qr);
  else
    assert(0);
}
il void upd(int p) { // 向上维护
  if (T[p].l == T[p].r)
    p >>= 1;
  while (p)
    pushUp(p), p >>= 1;
}
} // namespace SegmentTree

void dfs1(int x, int pre) { // 树剖 dfs1
  sz[x] = 1, hson[x] = 0, fa[x] = pre, dep[x] = dep[pre] + 1;
  for (int v : T[x]) {
    if (v == pre)
      continue;
    dfs1(v, x);
    sz[v] += sz[x], hson[x] = sz[v] > sz[hson[x]] ? v : hson[x];
    // hson 是重孩子
  }
}
void dfs2(int x, int tp) { // 树剖 dfs2
  id[x] = ++cnt, dfn[cnt] = x, g[x][1] = a[x], g[x][0] = 0,
  f[x][1] = f[x][0] = 0, top[x] = tp, ed[tp] = max(ed[tp], cnt);
  if (!hson[x]) // 叶子结点
    return f[x][1] = a[x], void();
  dfs2(hson[x], tp);
  for (int v : T[x]) {
    if (v == fa[x] || v == hson[x])
      continue;
    dfs2(v, v);
    g[x][1] += f[v][0], g[x][0] += max(f[v][1], f[v][0]);
  }
  f[x][0] = max(f[hson[x]][0] + g[x][0], f[hson[x]][1] + g[x][0]);
  f[x][1] = f[hson[x]][0] + g[x][1];
}
il void upd(int pos, int val) { // 把真实编号为 pos 的节点权值修改为 val
  Matrix tmp, tmp2;
  using SegmentTree::segtPtr;
  using SegmentTree::T;
  T[segtPtr[pos]].val[{1, 0}] += val - a[pos], a[pos] = val;
  while (true) {
    // 修改线段树
    tmp = SegmentTree::qry(1, id[top[pos]], ed[top[pos]]);
    SegmentTree::upd(segtPtr[pos]);
    tmp2 = SegmentTree::qry(1, id[top[pos]], ed[top[pos]]);

    pos = fa[top[pos]];
    if (!pos)
      return;
    // 修改矩阵
    Matrix &cur = T[segtPtr[pos]].val;
    cur[{0, 0}] +=
        max(tmp2[{0, 0}], tmp2[{1, 0}]) - max(tmp[{0, 0}], tmp[{1, 0}]);
    cur[{0, 1}] = cur[{0, 0}];
    cur[{1, 0}] += tmp2[{0, 0}] - tmp[{0, 0}];
    cur[{1, 1}] = -1e9;
  }
}
il int qry() { // 询问
  Matrix ans = SegmentTree::qry(1, id[1], ed[1]);
  return max(ans[{0, 0}], ans[{1, 0}]);
}

signed main() {
  read(n, Q);
  For(i, 1, n) read(a[i]);
  For(i, 1, n - 1) {
    int u, v;
    read(u, v);
    T[u].pb(v), T[v].pb(u);
  }
  dfs1(1, 0);
  top[1] = 1, dfs2(1, 1);
  SegmentTree::build(1, 1, n);
  while (Q--) {
    int x, y;
    read(x, y);
    upd(x, y);
    printf("%d\n", qry());
  }
  return 0;
}
2023/6/30 20:31
加载中...