MnZn代码求hack
查看原帖
MnZn代码求hack
676634
Albert_Wei楼主2023/6/25 21:50
#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int MaxN = 5e6 + 5, MaxL = 15;
const int MaxBL = 4e5, Maxcnt = 1e4;
namespace SpRMQ {
  int ST[MaxBL][MaxL], Ans[Maxcnt][MaxL][MaxL], IDST[MaxBL][MaxL];
  int Siz, BL, L[MaxBL], R[MaxBL], Bel[MaxN], Type[MaxBL], Lg[MaxBL];
  inline void Init(int n, int *A) {
  	Siz = max((int)(log2(n)) >> 1, 1ll);
  	BL = (n + Siz - 1) / Siz;
  	for (int i = 1; i <= n; i++) {
  	  Bel[i] = (i + Siz - 1) / Siz;
	}
	for (int i = 0, pw = 1; pw <= BL; i++, pw <<= 1) {
	  for (int j = 1; j + pw - 1 <= BL; j++) {
	  	ST[j][i] = 1e18;
	  }
	}
	Lg[0] = -1;
	for (int i = 1; i <= BL; i++) {
	  L[i] = (i - 1) * Siz + 1;
	  R[i] = min(i * Siz, n);
	  Lg[i] = Lg[i >> 1] + 1;
	  Type[i] = 0;
	  for (int j = L[i]; j <= R[i]; j++) {
	  	if (A[j] < ST[i][0]) {
	  	  ST[i][0] = A[j];
	  	  IDST[i][0] = j;
		}
	  	if (j >= L[i] + 1) {
	  	  int Num = (A[j] > A[j - 1] ? 1 : 0);
	  	  Type[i] += Num << (j - L[i] - 1);
		}
	  }
	}
    for (int i = 0, pw = 1; (pw << 1) <= BL; i++, pw <<= 1) {
      for (int j = 1; j + (pw << 1) - 1 <= BL; j++) {
      	if (ST[j][i] < ST[j + pw][i]) {
      	  ST[j][i + 1] = ST[j][i];
      	  IDST[j][i + 1] = IDST[j][i];
		} else {
		  ST[j][i + 1] = ST[j + pw][i];
		  IDST[j][i + 1] = IDST[j + pw][i];
		}
	  }
	}
	for (int i = 0; i < 1 << (Siz - 1); i++) {
	  vector<int> Val(Siz);
	  Val[0] = 0;
	  for (int j = 1, pw = 1; j < Siz; j++, pw <<= 1) {
	  	Val[j] = Val[j - 1] + (i & pw ? 1 : -1);
	  }
	  for (int j = 0; j < Siz; j++) {
	  	int Min = 1e18, Id;
	  	for (int k = j; k < Siz; k++) {
	  	  if (Val[k] < Min) {
	  	  	Min = Val[k];
	  	  	Id = k;
		  }
		  Ans[i][j][k] = Id;
		}
	  }
	}
  }
  inline int Query(int l, int r, int *A) {
  	if (l > r) {
  	  swap(l, r);
	}
	int LB = Bel[l], RB = Bel[r];
  	if (Bel[l] != Bel[r]) {
  	  int Bl = Bel[l] + 1, Br = Bel[r] - 1, ans, ID;
  	  if (Br < Bl) {
  	  	ans = 1e18;
	  } else {
	    int Log = Lg[Br - Bl + 1];
		if (ST[Bl][Log] < ST[Br - (1ll << Log) + 1][Log]) {
		  ans = ST[Bl][Log];
		  ID = IDST[Bl][Log];
		} else {
		  ans = ST[Br - (1ll << Log) + 1][Log];
		  ID = IDST[Br - (1ll << Log) + 1][Log];
		}
	  }
	  int Suf = Ans[Type[LB]][l - L[LB]][R[LB] - L[LB]] + L[LB];
	  int Pre = Ans[Type[RB]][0][r - L[RB]] + L[RB];
	  if (ans < A[Suf] && ans < A[Pre]) {
	  	return ID;
	  } else {
  	    if (A[Suf] < A[Pre]) {
  	  	  return Suf;
		} else {
		  return Pre;
		}
	  }
	} else {
	  return Ans[Type[LB]][l - L[LB]][r - L[LB]] + L[LB];
	}
  }
}

namespace LCA {
  vector<int> Ch[MaxN];
  int cur, Depth[MaxN], Num[MaxN], Dfn[MaxN];
  inline void Dfs(int x, int Dep) {
  	Dfn[x] = ++cur;
  	Num[cur] = x;
  	Depth[cur] = Dep;
  	for (auto i : Ch[x]) {
      Dfs(i, Dep + 1);
	  Num[++cur] = x;
   	  Depth[cur] = Dep;
	}
  }
  inline void Init(int n, int rt, int *pr) {
  	cur = 0; 
    for (int i = 1; i <= n; i++) {
  	  Ch[pr[i]].push_back(i);
	}
	Dfs(rt, 1);
	SpRMQ::Init((n << 1) - 1, Depth);
  }
  inline int LCA(int x, int y) {
	return Num[SpRMQ::Query(Dfn[x], Dfn[y], Depth)];
  }
}

vector<int> e[MaxN];
int n, m, rt, pr[MaxN] = {0};
inline void dfs(int x) {
  for (auto i : e[x]) {
  	if (i != pr[x]) {
  	  pr[i] = x;
  	  dfs(i);
	}
  }
}

signed main() {
  cin >> n >> m >> rt;
  for (int i = 1, u, v; i < n; i++) {
  	cin >> u >> v;
  	e[u].push_back(v), e[v].push_back(u);
  }
  dfs(rt);
  LCA::Init(n, rt, pr);
  for (int i = 1, u, v; i <= m; i++) {
    cin >> u >> v;
    cout << LCA::LCA(u, v) << endl;
  }
  return 0;
}

2023/6/25 21:50
加载中...