QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#869920 | #8616. Fast Tree Queries | ucup-team087# | TL | 2676ms | 20580kb | C++23 | 29.5kb | 2025-01-25 13:55:29 | 2025-01-25 13:55:30 |
Judging History
answer
#line 1 "library/my_template.hpp"
#if defined(LOCAL)
#include <my_template_compiled.hpp>
#else
// https://codeforces.com/blog/entry/96344
#pragma GCC optimize("Ofast,unroll-loops")
// いまの CF だとこれ入れると動かない?
// #pragma GCC target("avx2,popcnt")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i128 = __int128;
using u128 = unsigned __int128;
using f128 = __float128;
template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'010'000'000;
template <>
constexpr ll infty<ll> = 2'020'000'000'000'000'000;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * 2'000'000'000'000'000'000;
template <>
constexpr double infty<double> = infty<ll>;
template <>
constexpr long double infty<long double> = infty<ll>;
using pi = pair<ll, ll>;
using vi = vector<ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...) \
vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
// https://trap.jp/post/1224/
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)
#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define stoi stoll
int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
int popcnt_sgn(int x) { return (__builtin_parity(unsigned(x)) & 1 ? -1 : 1); }
int popcnt_sgn(u32 x) { return (__builtin_parity(x) & 1 ? -1 : 1); }
int popcnt_sgn(ll x) { return (__builtin_parityll(x) & 1 ? -1 : 1); }
int popcnt_sgn(u64 x) { return (__builtin_parityll(x) & 1 ? -1 : 1); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
template <typename T>
T kth_bit(int k) {
return T(1) << k;
}
template <typename T>
bool has_kth_bit(T x, int k) {
return x >> k & 1;
}
template <typename UINT>
struct all_bit {
struct iter {
UINT s;
iter(UINT s) : s(s) {}
int operator*() const { return lowbit(s); }
iter &operator++() {
s &= s - 1;
return *this;
}
bool operator!=(const iter) const { return s != 0; }
};
UINT s;
all_bit(UINT s) : s(s) {}
iter begin() const { return iter(s); }
iter end() const { return iter(0); }
};
template <typename UINT>
struct all_subset {
static_assert(is_unsigned<UINT>::value);
struct iter {
UINT s, t;
bool ed;
iter(UINT s) : s(s), t(s), ed(0) {}
int operator*() const { return s ^ t; }
iter &operator++() {
(t == 0 ? ed = 1 : t = (t - 1) & s);
return *this;
}
bool operator!=(const iter) const { return !ed; }
};
UINT s;
all_subset(UINT s) : s(s) {}
iter begin() const { return iter(s); }
iter end() const { return iter(0); }
};
template <typename T>
T floor(T a, T b) {
return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
return floor(x + y - 1, y);
}
template <typename T>
T bmod(T x, T y) {
return x - y * floor(x, y);
}
template <typename T>
pair<T, T> divmod(T x, T y) {
T q = floor(x, y);
return {q, x - q * y};
}
template <typename T, typename U>
T SUM(const vector<U> &A) {
T sm = 0;
for (auto &&a: A) sm += a;
return sm;
}
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end()), x.shrink_to_fit()
template <typename T>
T POP(deque<T> &que) {
T a = que.front();
que.pop_front();
return a;
}
template <typename T>
T POP(pq<T> &que) {
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(pqg<T> &que) {
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(vc<T> &que) {
T a = que.back();
que.pop_back();
return a;
}
template <typename F>
ll binary_search(F check, ll ok, ll ng, bool check_ok = true) {
if (check_ok) assert(check(ok));
while (abs(ok - ng) > 1) {
auto x = (ng + ok) / 2;
(check(x) ? ok : ng) = x;
}
return ok;
}
template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
FOR(iter) {
double x = (ok + ng) / 2;
(check(x) ? ok : ng) = x;
}
return (ok + ng) / 2;
}
template <class T, class S>
inline bool chmax(T &a, const S &b) {
return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
return (a > b ? a = b, 1 : 0);
}
// ? は -1
vc<int> s_to_vi(const string &S, char first_char) {
vc<int> A(S.size());
FOR(i, S.size()) { A[i] = (S[i] != '?' ? S[i] - first_char : -1); }
return A;
}
template <typename T, typename U>
vector<T> cumsum(vector<U> &A, int off = 1) {
int N = A.size();
vector<T> B(N + 1);
FOR(i, N) { B[i + 1] = B[i] + A[i]; }
if (off == 0) B.erase(B.begin());
return B;
}
// stable sort
template <typename T>
vector<int> argsort(const vector<T> &A) {
vector<int> ids(len(A));
iota(all(ids), 0);
sort(all(ids), [&](int i, int j) { return (A[i] == A[j] ? i < j : A[i] < A[j]); });
return ids;
}
// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
vc<T> B(len(I));
FOR(i, len(I)) B[i] = A[I[i]];
return B;
}
template <typename T, typename... Vectors>
void concat(vc<T> &first, const Vectors &... others) {
vc<T> &res = first;
(res.insert(res.end(), others.begin(), others.end()), ...);
}
#endif
#line 1 "library/other/io.hpp"
#define FASTIO
#include <unistd.h>
// https://judge.yosupo.jp/submission/21623
namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf
uint32_t pil = 0, pir = 0, por = 0;
struct Pre {
char num[10000][4];
constexpr Pre() : num() {
for (int i = 0; i < 10000; i++) {
int n = i;
for (int j = 3; j >= 0; j--) {
num[i][j] = n % 10 | '0';
n /= 10;
}
}
}
} constexpr pre;
inline void load() {
memcpy(ibuf, ibuf + pil, pir - pil);
pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
pil = 0;
if (pir < SZ) ibuf[pir++] = '\n';
}
inline void flush() {
fwrite(obuf, 1, por, stdout);
por = 0;
}
void rd(char &c) {
do {
if (pil + 1 > pir) load();
c = ibuf[pil++];
} while (isspace(c));
}
void rd(string &x) {
x.clear();
char c;
do {
if (pil + 1 > pir) load();
c = ibuf[pil++];
} while (isspace(c));
do {
x += c;
if (pil == pir) load();
c = ibuf[pil++];
} while (!isspace(c));
}
template <typename T>
void rd_real(T &x) {
string s;
rd(s);
x = stod(s);
}
template <typename T>
void rd_integer(T &x) {
if (pil + 100 > pir) load();
char c;
do
c = ibuf[pil++];
while (c < '-');
bool minus = 0;
if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
if (c == '-') { minus = 1, c = ibuf[pil++]; }
}
x = 0;
while ('0' <= c) { x = x * 10 + (c & 15), c = ibuf[pil++]; }
if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
if (minus) x = -x;
}
}
void rd(int &x) { rd_integer(x); }
void rd(ll &x) { rd_integer(x); }
void rd(i128 &x) { rd_integer(x); }
void rd(u32 &x) { rd_integer(x); }
void rd(u64 &x) { rd_integer(x); }
void rd(u128 &x) { rd_integer(x); }
void rd(double &x) { rd_real(x); }
void rd(long double &x) { rd_real(x); }
void rd(f128 &x) { rd_real(x); }
template <class T, class U>
void rd(pair<T, U> &p) {
return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T>
void rd_tuple(T &t) {
if constexpr (N < std::tuple_size<T>::value) {
auto &x = std::get<N>(t);
rd(x);
rd_tuple<N + 1>(t);
}
}
template <class... T>
void rd(tuple<T...> &tpl) {
rd_tuple(tpl);
}
template <size_t N = 0, typename T>
void rd(array<T, N> &x) {
for (auto &d: x) rd(d);
}
template <class T>
void rd(vc<T> &x) {
for (auto &d: x) rd(d);
}
void read() {}
template <class H, class... T>
void read(H &h, T &... t) {
rd(h), read(t...);
}
void wt(const char c) {
if (por == SZ) flush();
obuf[por++] = c;
}
void wt(const string s) {
for (char c: s) wt(c);
}
void wt(const char *s) {
size_t len = strlen(s);
for (size_t i = 0; i < len; i++) wt(s[i]);
}
template <typename T>
void wt_integer(T x) {
if (por > SZ - 100) flush();
if (x < 0) { obuf[por++] = '-', x = -x; }
int outi;
for (outi = 96; x >= 10000; outi -= 4) {
memcpy(out + outi, pre.num[x % 10000], 4);
x /= 10000;
}
if (x >= 1000) {
memcpy(obuf + por, pre.num[x], 4);
por += 4;
} else if (x >= 100) {
memcpy(obuf + por, pre.num[x] + 1, 3);
por += 3;
} else if (x >= 10) {
int q = (x * 103) >> 10;
obuf[por] = q | '0';
obuf[por + 1] = (x - q * 10) | '0';
por += 2;
} else
obuf[por++] = x | '0';
memcpy(obuf + por, out + outi + 4, 96 - outi);
por += 96 - outi;
}
template <typename T>
void wt_real(T x) {
ostringstream oss;
oss << fixed << setprecision(15) << double(x);
string s = oss.str();
wt(s);
}
void wt(int x) { wt_integer(x); }
void wt(ll x) { wt_integer(x); }
void wt(i128 x) { wt_integer(x); }
void wt(u32 x) { wt_integer(x); }
void wt(u64 x) { wt_integer(x); }
void wt(u128 x) { wt_integer(x); }
void wt(double x) { wt_real(x); }
void wt(long double x) { wt_real(x); }
void wt(f128 x) { wt_real(x); }
template <class T, class U>
void wt(const pair<T, U> val) {
wt(val.first);
wt(' ');
wt(val.second);
}
template <size_t N = 0, typename T>
void wt_tuple(const T t) {
if constexpr (N < std::tuple_size<T>::value) {
if constexpr (N > 0) { wt(' '); }
const auto x = std::get<N>(t);
wt(x);
wt_tuple<N + 1>(t);
}
}
template <class... T>
void wt(tuple<T...> tpl) {
wt_tuple(tpl);
}
template <class T, size_t S>
void wt(const array<T, S> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) wt(' ');
wt(val[i]);
}
}
template <class T>
void wt(const vector<T> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) wt(' ');
wt(val[i]);
}
}
void print() { wt('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
wt(head);
if (sizeof...(Tail)) wt(' ');
print(forward<Tail>(tail)...);
}
// gcc expansion. called automaticall after main.
void __attribute__((destructor)) _d() { flush(); }
} // namespace fastio
using fastio::read;
using fastio::print;
using fastio::flush;
#if defined(LOCAL)
#define SHOW(...) SHOW_IMPL(__VA_ARGS__, SHOW6, SHOW5, SHOW4, SHOW3, SHOW2, SHOW1)(__VA_ARGS__)
#define SHOW_IMPL(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
#define SHOW1(x) print(#x, "=", (x)), flush()
#define SHOW2(x, y) print(#x, "=", (x), #y, "=", (y)), flush()
#define SHOW3(x, y, z) print(#x, "=", (x), #y, "=", (y), #z, "=", (z)), flush()
#define SHOW4(x, y, z, w) print(#x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w)), flush()
#define SHOW5(x, y, z, w, v) print(#x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", (v)), flush()
#define SHOW6(x, y, z, w, v, u) print(#x, "=", (x), #y, "=", (y), #z, "=", (z), #w, "=", (w), #v, "=", (v), #u, "=", (u)), flush()
#else
#define SHOW(...)
#endif
#define INT(...) \
int __VA_ARGS__; \
read(__VA_ARGS__)
#define LL(...) \
ll __VA_ARGS__; \
read(__VA_ARGS__)
#define U32(...) \
u32 __VA_ARGS__; \
read(__VA_ARGS__)
#define U64(...) \
u64 __VA_ARGS__; \
read(__VA_ARGS__)
#define STR(...) \
string __VA_ARGS__; \
read(__VA_ARGS__)
#define CHAR(...) \
char __VA_ARGS__; \
read(__VA_ARGS__)
#define DBL(...) \
double __VA_ARGS__; \
read(__VA_ARGS__)
#define VEC(type, name, size) \
vector<type> name(size); \
read(name)
#define VV(type, name, h, w) \
vector<vector<type>> name(h, vector<type>(w)); \
read(name)
void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
void YA(bool t = 1) { print(t ? "YA" : "TIDAK"); }
void TIDAK(bool t = 1) { YES(!t); }
#line 3 "main.cpp"
#line 2 "library/graph/tree.hpp"
#line 2 "library/ds/hashmap.hpp"
// u64 -> Val
template <typename Val>
struct HashMap {
// n は入れたいものの個数で ok
HashMap(u32 n = 0) { build(n); }
void build(u32 n) {
u32 k = 8;
while (k < n * 2) k *= 2;
cap = k / 2, mask = k - 1;
key.resize(k), val.resize(k), used.assign(k, 0);
}
// size を保ったまま. size=0 にするときは build すること.
void clear() {
used.assign(len(used), 0);
cap = (mask + 1) / 2;
}
int size() { return len(used) / 2 - cap; }
int index(const u64& k) {
int i = 0;
for (i = hash(k); used[i] && key[i] != k; i = (i + 1) & mask) {}
return i;
}
Val& operator[](const u64& k) {
if (cap == 0) extend();
int i = index(k);
if (!used[i]) { used[i] = 1, key[i] = k, val[i] = Val{}, --cap; }
return val[i];
}
Val get(const u64& k, Val default_value) {
int i = index(k);
return (used[i] ? val[i] : default_value);
}
bool count(const u64& k) {
int i = index(k);
return used[i] && key[i] == k;
}
// f(key, val)
template <typename F>
void enumerate_all(F f) {
FOR(i, len(used)) if (used[i]) f(key[i], val[i]);
}
private:
u32 cap, mask;
vc<u64> key;
vc<Val> val;
vc<bool> used;
u64 hash(u64 x) {
static const u64 FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count();
x += FIXED_RANDOM;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return (x ^ (x >> 31)) & mask;
}
void extend() {
vc<pair<u64, Val>> dat;
dat.reserve(len(used) / 2 - cap);
FOR(i, len(used)) {
if (used[i]) dat.eb(key[i], val[i]);
}
build(2 * len(dat));
for (auto& [a, b]: dat) (*this)[a] = b;
}
};
#line 3 "library/graph/base.hpp"
template <typename T>
struct Edge {
int frm, to;
T cost;
int id;
};
template <typename T = int, bool directed = false>
struct Graph {
static constexpr bool is_directed = directed;
int N, M;
using cost_type = T;
using edge_type = Edge<T>;
vector<edge_type> edges;
vector<int> indptr;
vector<edge_type> csr_edges;
vc<int> vc_deg, vc_indeg, vc_outdeg;
bool prepared;
class OutgoingEdges {
public:
OutgoingEdges(const Graph* G, int l, int r) : G(G), l(l), r(r) {}
const edge_type* begin() const {
if (l == r) { return 0; }
return &G->csr_edges[l];
}
const edge_type* end() const {
if (l == r) { return 0; }
return &G->csr_edges[r];
}
private:
const Graph* G;
int l, r;
};
bool is_prepared() { return prepared; }
Graph() : N(0), M(0), prepared(0) {}
Graph(int N) : N(N), M(0), prepared(0) {}
void build(int n) {
N = n, M = 0;
prepared = 0;
edges.clear();
indptr.clear();
csr_edges.clear();
vc_deg.clear();
vc_indeg.clear();
vc_outdeg.clear();
}
void add(int frm, int to, T cost = 1, int i = -1) {
assert(!prepared);
assert(0 <= frm && 0 <= to && to < N);
if (i == -1) i = M;
auto e = edge_type({frm, to, cost, i});
edges.eb(e);
++M;
}
#ifdef FASTIO
// wt, off
void read_tree(bool wt = false, int off = 1) { read_graph(N - 1, wt, off); }
void read_graph(int M, bool wt = false, int off = 1) {
for (int m = 0; m < M; ++m) {
INT(a, b);
a -= off, b -= off;
if (!wt) {
add(a, b);
} else {
T c;
read(c);
add(a, b, c);
}
}
build();
}
#endif
void build() {
assert(!prepared);
prepared = true;
indptr.assign(N + 1, 0);
for (auto&& e: edges) {
indptr[e.frm + 1]++;
if (!directed) indptr[e.to + 1]++;
}
for (int v = 0; v < N; ++v) { indptr[v + 1] += indptr[v]; }
auto counter = indptr;
csr_edges.resize(indptr.back() + 1);
for (auto&& e: edges) {
csr_edges[counter[e.frm]++] = e;
if (!directed) csr_edges[counter[e.to]++] = edge_type({e.to, e.frm, e.cost, e.id});
}
}
OutgoingEdges operator[](int v) const {
assert(prepared);
return {this, indptr[v], indptr[v + 1]};
}
vc<int> deg_array() {
if (vc_deg.empty()) calc_deg();
return vc_deg;
}
pair<vc<int>, vc<int>> deg_array_inout() {
if (vc_indeg.empty()) calc_deg_inout();
return {vc_indeg, vc_outdeg};
}
int deg(int v) {
if (vc_deg.empty()) calc_deg();
return vc_deg[v];
}
int in_deg(int v) {
if (vc_indeg.empty()) calc_deg_inout();
return vc_indeg[v];
}
int out_deg(int v) {
if (vc_outdeg.empty()) calc_deg_inout();
return vc_outdeg[v];
}
#ifdef FASTIO
void debug() {
print("Graph");
if (!prepared) {
print("frm to cost id");
for (auto&& e: edges) print(e.frm, e.to, e.cost, e.id);
} else {
print("indptr", indptr);
print("frm to cost id");
FOR(v, N) for (auto&& e: (*this)[v]) print(e.frm, e.to, e.cost, e.id);
}
}
#endif
vc<int> new_idx;
vc<bool> used_e;
// G における頂点 V[i] が、新しいグラフで i になるようにする
// {G, es}
// sum(deg(v)) の計算量になっていて、
// 新しいグラフの n+m より大きい可能性があるので注意
Graph<T, directed> rearrange(vc<int> V, bool keep_eid = 0) {
if (len(new_idx) != N) new_idx.assign(N, -1);
int n = len(V);
FOR(i, n) new_idx[V[i]] = i;
Graph<T, directed> G(n);
vc<int> history;
FOR(i, n) {
for (auto&& e: (*this)[V[i]]) {
if (len(used_e) <= e.id) used_e.resize(e.id + 1);
if (used_e[e.id]) continue;
int a = e.frm, b = e.to;
if (new_idx[a] != -1 && new_idx[b] != -1) {
history.eb(e.id);
used_e[e.id] = 1;
int eid = (keep_eid ? e.id : -1);
G.add(new_idx[a], new_idx[b], e.cost, eid);
}
}
}
FOR(i, n) new_idx[V[i]] = -1;
for (auto&& eid: history) used_e[eid] = 0;
G.build();
return G;
}
Graph<T, true> to_directed_tree(int root = -1) {
if (root == -1) root = 0;
assert(!is_directed && prepared && M == N - 1);
Graph<T, true> G1(N);
vc<int> par(N, -1);
auto dfs = [&](auto& dfs, int v) -> void {
for (auto& e: (*this)[v]) {
if (e.to == par[v]) continue;
par[e.to] = v, dfs(dfs, e.to);
}
};
dfs(dfs, root);
for (auto& e: edges) {
int a = e.frm, b = e.to;
if (par[a] == b) swap(a, b);
assert(par[b] == a);
G1.add(a, b, e.cost);
}
G1.build();
return G1;
}
HashMap<int> MP_FOR_EID;
int get_eid(u64 a, u64 b) {
if (len(MP_FOR_EID) == 0) {
MP_FOR_EID.build(N - 1);
for (auto& e: edges) {
u64 a = e.frm, b = e.to;
u64 k = to_eid_key(a, b);
MP_FOR_EID[k] = e.id;
}
}
return MP_FOR_EID.get(to_eid_key(a, b), -1);
}
u64 to_eid_key(u64 a, u64 b) {
if (!directed && a > b) swap(a, b);
return N * a + b;
}
private:
void calc_deg() {
assert(vc_deg.empty());
vc_deg.resize(N);
for (auto&& e: edges) vc_deg[e.frm]++, vc_deg[e.to]++;
}
void calc_deg_inout() {
assert(vc_indeg.empty());
vc_indeg.resize(N);
vc_outdeg.resize(N);
for (auto&& e: edges) { vc_indeg[e.to]++, vc_outdeg[e.frm]++; }
}
};
#line 4 "library/graph/tree.hpp"
// HLD euler tour をとっていろいろ。
template <typename GT>
struct Tree {
using Graph_type = GT;
GT &G;
using WT = typename GT::cost_type;
int N;
vector<int> LID, RID, head, V, parent, VtoE;
vc<int> depth;
vc<WT> depth_weighted;
Tree(GT &G, int r = 0, bool hld = 1) : G(G) { build(r, hld); }
void build(int r = 0, bool hld = 1) {
if (r == -1) return; // build を遅延したいとき
N = G.N;
LID.assign(N, -1), RID.assign(N, -1), head.assign(N, r);
V.assign(N, -1), parent.assign(N, -1), VtoE.assign(N, -1);
depth.assign(N, -1), depth_weighted.assign(N, 0);
assert(G.is_prepared());
int t1 = 0;
dfs_sz(r, -1, hld);
dfs_hld(r, t1);
}
void dfs_sz(int v, int p, bool hld) {
auto &sz = RID;
parent[v] = p;
depth[v] = (p == -1 ? 0 : depth[p] + 1);
sz[v] = 1;
int l = G.indptr[v], r = G.indptr[v + 1];
auto &csr = G.csr_edges;
// 使う辺があれば先頭にする
for (int i = r - 2; i >= l; --i) {
if (hld && depth[csr[i + 1].to] == -1) swap(csr[i], csr[i + 1]);
}
int hld_sz = 0;
for (int i = l; i < r; ++i) {
auto e = csr[i];
if (depth[e.to] != -1) continue;
depth_weighted[e.to] = depth_weighted[v] + e.cost;
VtoE[e.to] = e.id;
dfs_sz(e.to, v, hld);
sz[v] += sz[e.to];
if (hld && chmax(hld_sz, sz[e.to]) && l < i) { swap(csr[l], csr[i]); }
}
}
void dfs_hld(int v, int ×) {
LID[v] = times++;
RID[v] += LID[v];
V[LID[v]] = v;
bool heavy = true;
for (auto &&e: G[v]) {
if (depth[e.to] <= depth[v]) continue;
head[e.to] = (heavy ? head[v] : e.to);
heavy = false;
dfs_hld(e.to, times);
}
}
vc<int> heavy_path_at(int v) {
vc<int> P = {v};
while (1) {
int a = P.back();
for (auto &&e: G[a]) {
if (e.to != parent[a] && head[e.to] == v) {
P.eb(e.to);
break;
}
}
if (P.back() == a) break;
}
return P;
}
int heavy_child(int v) {
int k = LID[v] + 1;
if (k == N) return -1;
int w = V[k];
return (parent[w] == v ? w : -1);
}
int e_to_v(int eid) {
auto e = G.edges[eid];
return (parent[e.frm] == e.to ? e.frm : e.to);
}
int v_to_e(int v) { return VtoE[v]; }
int get_eid(int u, int v) {
if (parent[u] != v) swap(u, v);
assert(parent[u] == v);
return VtoE[u];
}
int ELID(int v) { return 2 * LID[v] - depth[v]; }
int ERID(int v) { return 2 * RID[v] - depth[v] - 1; }
// 目標地点へ進む個数が k
int LA(int v, int k) {
assert(k <= depth[v]);
while (1) {
int u = head[v];
if (LID[v] - k >= LID[u]) return V[LID[v] - k];
k -= LID[v] - LID[u] + 1;
v = parent[u];
}
}
int la(int u, int v) { return LA(u, v); }
int LCA(int u, int v) {
for (;; v = parent[head[v]]) {
if (LID[u] > LID[v]) swap(u, v);
if (head[u] == head[v]) return u;
}
}
int meet(int a, int b, int c) { return LCA(a, b) ^ LCA(a, c) ^ LCA(b, c); }
int lca(int u, int v) { return LCA(u, v); }
int subtree_size(int v, int root = -1) {
if (root == -1) return RID[v] - LID[v];
if (v == root) return N;
int x = jump(v, root, 1);
if (in_subtree(v, x)) return RID[v] - LID[v];
return N - RID[x] + LID[x];
}
int dist(int a, int b) {
int c = LCA(a, b);
return depth[a] + depth[b] - 2 * depth[c];
}
WT dist_weighted(int a, int b) {
int c = LCA(a, b);
return depth_weighted[a] + depth_weighted[b] - WT(2) * depth_weighted[c];
}
// a is in b
bool in_subtree(int a, int b) { return LID[b] <= LID[a] && LID[a] < RID[b]; }
int jump(int a, int b, ll k) {
if (k == 1) {
if (a == b) return -1;
return (in_subtree(b, a) ? LA(b, depth[b] - depth[a] - 1) : parent[a]);
}
int c = LCA(a, b);
int d_ac = depth[a] - depth[c];
int d_bc = depth[b] - depth[c];
if (k > d_ac + d_bc) return -1;
if (k <= d_ac) return LA(a, k);
return LA(b, d_ac + d_bc - k);
}
vc<int> collect_child(int v) {
vc<int> res;
for (auto &&e: G[v])
if (e.to != parent[v]) res.eb(e.to);
return res;
}
vc<int> collect_light(int v) {
vc<int> res;
bool skip = true;
for (auto &&e: G[v])
if (e.to != parent[v]) {
if (!skip) res.eb(e.to);
skip = false;
}
return res;
}
vc<pair<int, int>> get_path_decomposition(int u, int v, bool edge) {
// [始点, 終点] の"閉"区間列。
vc<pair<int, int>> up, down;
while (1) {
if (head[u] == head[v]) break;
if (LID[u] < LID[v]) {
down.eb(LID[head[v]], LID[v]);
v = parent[head[v]];
} else {
up.eb(LID[u], LID[head[u]]);
u = parent[head[u]];
}
}
if (LID[u] < LID[v]) down.eb(LID[u] + edge, LID[v]);
elif (LID[v] + edge <= LID[u]) up.eb(LID[u], LID[v] + edge);
reverse(all(down));
up.insert(up.end(), all(down));
return up;
}
// 辺の列の情報 (frm,to,str)
// str = "heavy_up", "heavy_down", "light_up", "light_down"
vc<tuple<int, int, string>> get_path_decomposition_detail(int u, int v) {
vc<tuple<int, int, string>> up, down;
while (1) {
if (head[u] == head[v]) break;
if (LID[u] < LID[v]) {
if (v != head[v]) down.eb(head[v], v, "heavy_down"), v = head[v];
down.eb(parent[v], v, "light_down"), v = parent[v];
} else {
if (u != head[u]) up.eb(u, head[u], "heavy_up"), u = head[u];
up.eb(u, parent[u], "light_up"), u = parent[u];
}
}
if (LID[u] < LID[v]) down.eb(u, v, "heavy_down");
elif (LID[v] < LID[u]) up.eb(u, v, "heavy_up");
reverse(all(down));
concat(up, down);
return up;
}
vc<int> restore_path(int u, int v) {
vc<int> P;
for (auto &&[a, b]: get_path_decomposition(u, v, 0)) {
if (a <= b) {
FOR(i, a, b + 1) P.eb(V[i]);
} else {
FOR_R(i, b, a + 1) P.eb(V[i]);
}
}
return P;
}
// path [a,b] と [c,d] の交わり. 空ならば {-1,-1}.
// https://codeforces.com/problemset/problem/500/G
pair<int, int> path_intersection(int a, int b, int c, int d) {
int ab = lca(a, b), ac = lca(a, c), ad = lca(a, d);
int bc = lca(b, c), bd = lca(b, d), cd = lca(c, d);
int x = ab ^ ac ^ bc, y = ab ^ ad ^ bd; // meet(a,b,c), meet(a,b,d)
if (x != y) return {x, y};
int z = ac ^ ad ^ cd;
if (x != z) x = -1;
return {x, x};
}
// uv path 上で check(v) を満たす最後の v
// なければ (つまり check(v) が ng )-1
template <class F>
int max_path(F check, int u, int v) {
if (!check(u)) return -1;
auto pd = get_path_decomposition(u, v, false);
for (auto [a, b]: pd) {
if (!check(V[a])) return u;
if (check(V[b])) {
u = V[b];
continue;
}
int c = binary_search([&](int c) -> bool { return check(V[c]); }, a, b, 0);
return V[c];
}
return u;
}
};
#line 5 "main.cpp"
int A[100'000];
void solve() {
LL(N, Q);
Graph<int, 0> G(N);
G.read_tree();
Tree<decltype(G)> tree(G);
auto& V = tree.V;
FOR(i, N) A[i] = 1 + V[i];
FOR(Q) {
STR(tp);
INT(a, b);
--a, --b;
auto pd = tree.get_path_decomposition(a, b, false);
for (auto& [s, t]: pd) {
if (s > t) swap(s, t);
++t;
}
if (tp == "+") {
INT(x);
// add x
for (auto& [s, t]: pd) {
SHOW(s, t);
for (int i = s; i < t; ++i) A[i] += x;
}
} else {
int ans = 0;
for (auto& [s, t]: pd) {
for (int i = s; i < t; ++i) ans ^= A[i];
}
print(ans);
}
}
}
signed main() { solve(); }
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3584kb
input:
5 6 1 2 1 3 3 4 3 5 ? 2 5 + 1 4 1 ? 2 5 + 4 5 2 ? 4 5 ? 1 1
output:
5 1 6 2
result:
ok 4 number(s): "5 1 6 2"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3712kb
input:
100 100 6 74 6 93 7 46 7 78 10 77 11 9 11 19 11 37 11 51 11 65 12 57 13 15 13 81 13 100 14 2 14 31 16 11 16 24 16 43 16 82 18 4 18 8 21 56 24 29 24 96 26 22 27 32 28 59 29 6 29 94 32 33 35 54 35 80 35 88 37 66 37 71 37 84 38 17 39 64 39 92 40 49 43 7 43 13 43 44 43 79 44 35 44 60 44 63 44 73 46 75 4...
output:
106 66 23766 20394 16388 3365 12076 7844 43127 56700 59 34700 24083 1164 24068 18776 3375 17495 21576 63126 11157 108177 63127 99162 105173 10715 110921 18320 19725 30958 120179 81226 107525 15669 21804 31071 63099 8313 191380 232240 84531 89146 173181 5447 160027 228651 98075 32595 109808 221822 11...
result:
ok 51 numbers
Test #3:
score: 0
Accepted
time: 3ms
memory: 4356kb
input:
10000 10000 1 8776 3 1597 3 8333 4 675 4 6993 4 7587 5 3379 5 6733 7 2440 7 6480 7 9506 10 4545 10 6664 12 1476 12 5343 14 1340 14 4167 14 5990 14 9910 15 5118 15 9423 16 8106 17 3856 20 5201 23 1138 24 3431 24 5578 25 251 26 3219 26 4156 26 6668 27 3795 28 6282 28 8196 34 9595 35 3919 36 5893 37 58...
output:
9911 12310 4793 31764 2730 42301 62944 16978 8306 25311 3011 1327 48224 8407 15662 38117 42837 59074 40600 39018 126441 21755 24519 51286 121187 4335 8349 10553 60726 86675 10797 3883 90069 95477 129342 37777 42339 124045 94323 16858 217612 79454 258856 118337 257945 196316 170121 216631 168616 1663...
result:
ok 5012 numbers
Test #4:
score: 0
Accepted
time: 23ms
memory: 7892kb
input:
50000 50000 1 1362 3 3371 3 13803 3 41794 3 47253 5 6227 5 42748 5 47841 6 28509 6 47395 7 8651 8 35909 10 24241 10 31205 10 33574 10 44109 10 48982 12 31361 12 44645 13 42041 15 20480 16 9467 16 11685 16 16024 16 28894 16 30759 19 3485 19 23470 19 24714 22 14239 25 44841 31 20447 35 5378 35 45983 3...
output:
5042 36803 61033 62216 64370 9744 33748 43519 25564 87892 120265 52351 36778 1507 81138 124599 19620 169852 82219 106112 38410 47506 214605 229380 175036 184353 71808 135637 195043 213707 60790 86453 31176 26740 107180 117349 64903 55397 245841 33362 73881 227391 227333 52027 217335 146795 51029 100...
result:
ok 24888 numbers
Test #5:
score: 0
Accepted
time: 47ms
memory: 12468kb
input:
100000 100000 4 6907 4 36895 4 37669 4 43936 4 99352 5 70501 10 29516 11 2844 11 77315 13 67782 13 72511 14 17273 14 52833 16 97869 19 29567 20 150 20 22843 20 40110 20 55549 20 70574 22 19544 25 43083 26 6781 28 16286 31 54186 33 6987 33 30861 33 98931 35 1140 35 21137 35 26681 35 59133 35 68440 35...
output:
81605 93578 30029 52473 57143 63629 77074 53264 71956 49059 16958 120352 93046 80080 67928 99557 182425 198595 36952 180370 156161 98094 56273 28969 34287 146511 31057 171228 128057 13930 81021 69266 100431 118091 249004 63451 147951 223183 255240 173677 30490 137681 135801 8441 205904 32855 66449 2...
result:
ok 50026 numbers
Test #6:
score: 0
Accepted
time: 66ms
memory: 12716kb
input:
100000 100000 1 484 1 23605 4 29115 5 78235 6 41049 7 17427 7 59118 7 73639 8 11499 8 21824 11 1488 11 34365 11 46659 15 1670 15 18862 16 88552 17 6551 17 18453 17 22090 18 90500 19 7369 19 40175 19 88031 19 89418 20 82312 22 36035 22 37511 22 90587 24 26545 25 99359 26 9713 26 19360 26 23939 27 145...
output:
118339 49557 8069 129295 8844 117076 73582 44568 123694 84080 220459 65210 20353 78112 178132 238977 76360 242837 177610 55964 146913 258846 46783 101598 210987 130886 215693 137264 91070 47636 222290 212175 70753 64509 143987 258750 63355 124572 249779 144712 237288 64472 32941 26055 220986 221734 ...
result:
ok 50004 numbers
Test #7:
score: 0
Accepted
time: 331ms
memory: 14932kb
input:
100000 100000 2 96325 3 2625 3 19305 3 23547 3 33880 4 34351 4 80895 6 81122 7 8449 8 33132 9 6805 10 66297 12 40279 15 97995 17 28489 17 58943 17 63155 18 16755 19 36111 19 48497 20 73429 21 58028 22 23782 23 23210 25 43059 25 98782 28 96774 29 13371 30 18348 30 33119 31 91098 32 20761 34 19579 34 ...
output:
127926 27191 52198 17494 136 89133 88302 171 53017 111240 104493 80525 30736 39514 30186 242564 127960 116595 77217 181066 78202 117647 65124 5801 23054 231346 224212 101596 208931 56567 153986 225153 98732 39206 196696 201593 49107 59019 227567 23907 240224 47177 110143 93337 12687 16281 91369 7419...
result:
ok 49756 numbers
Test #8:
score: 0
Accepted
time: 477ms
memory: 16224kb
input:
100000 100000 1 18235 1 18934 2 89403 2 90291 3 31647 3 35123 4 14885 5 62625 6 75214 6 78206 6 86462 8 68147 10 73927 12 70742 13 18440 13 52686 14 486 15 38714 17 22417 19 10945 20 65914 22 168 24 72860 24 77513 25 43311 28 65572 31 24246 31 59430 32 26581 33 50532 35 41198 35 50438 38 10180 39 26...
output:
22351 118753 109047 88534 43548 60668 10313 43770 93628 94411 177029 257319 102775 45279 115695 72012 192085 82192 95036 247561 261897 165855 165273 226260 148341 25180 217815 163115 16411 218342 48666 2097 28168 215064 103606 87112 56628 51686 160381 172733 114741 224702 118590 202031 122700 81734 ...
result:
ok 50083 numbers
Test #9:
score: 0
Accepted
time: 620ms
memory: 17380kb
input:
100000 100000 1 11525 1 89745 2 67284 3 9976 4 50748 5 77041 6 78293 7 56148 8 96259 9 89843 10 27797 11 16227 12 42015 13 68712 14 79151 15 28737 16 12689 16 46963 17 28758 17 97100 18 9035 18 45786 19 90894 20 6079 21 74811 22 59751 24 46439 25 61997 26 49256 27 47844 27 94562 28 36184 28 66803 29...
output:
27686 112778 112901 88910 1259 100292 96264 120935 67017 16105 254118 72138 79696 90798 240510 79481 58592 122335 35752 50037 4041 228323 26517 261989 101035 109710 124017 214226 78961 147898 227267 88759 232759 3546 176037 13839 58194 199727 72664 208807 235932 95313 72316 175531 185967 46635 25389...
result:
ok 50026 numbers
Test #10:
score: 0
Accepted
time: 904ms
memory: 18792kb
input:
100000 100000 1 8418 2 20507 3 79696 4 480 5 96826 6 39218 7 33218 8 91962 9 61011 10 76027 11 51859 12 47310 13 9311 14 62652 15 54337 16 37358 17 8695 18 30671 19 48794 20 60657 21 52785 22 67049 23 53237 24 89488 25 75316 26 59632 27 67663 28 64116 29 55756 30 9293 31 94163 32 68737 33 19549 34 2...
output:
59881 78759 127664 105428 29216 107850 23544 72603 31268 104150 10678 99895 191639 208183 143507 28071 112078 206140 244014 94502 180431 86547 228779 253881 114121 78644 211819 183217 3147 260855 252995 92807 134492 222747 179363 178012 163544 6300 56553 216082 135851 241124 54901 160545 83866 34670...
result:
ok 50161 numbers
Test #11:
score: 0
Accepted
time: 909ms
memory: 17124kb
input:
100000 100000 1 65542 2 44999 3 44775 4 53755 5 91414 6 88642 7 43743 8 66023 9 81924 10 33144 11 16238 12 69557 13 88380 14 14104 15 1590 16 22493 17 76223 18 2992 19 59612 20 19262 21 44547 22 9268 23 12883 24 8940 25 89232 26 83134 27 39177 28 25894 29 66905 30 75897 31 68348 32 31913 33 37824 34...
output:
85995 93714 48766 33134 15475 33702 26879 252344 91559 31139 32105 17681 214842 50526 179 127372 79021 215907 232859 150665 37612 228872 251465 221167 238269 143930 94966 193052 240279 70502 210689 5253 244204 197389 79884 65172 23165 26916 135637 44849 246604 184554 131027 12149 145820 236776 27224...
result:
ok 49916 numbers
Test #12:
score: 0
Accepted
time: 1472ms
memory: 20580kb
input:
100000 100000 1 20244 2 70573 3 10436 4 38605 5 82242 6 7959 7 41794 8 6055 9 31572 10 18325 11 47705 12 92257 13 84847 14 29103 15 56455 16 78786 17 15635 18 46887 19 42925 20 73042 21 13655 22 17805 23 79078 24 2264 25 75041 26 20673 27 67835 28 26420 29 43093 30 18005 31 30599 32 67822 33 74865 3...
output:
57973 49029 120357 260910 16992 270917 140712 61400 151081 193091 45372 245217 372812 730619 84632 443274 274702 287820 414375 965786 802481 1047701 620743 227679 563632 989174 510166 711609 1202310 1778396 696203 940565 166128 1123056 1109958 1219135 89745 975640 1434947 1480887 1051570 1795047 219...
result:
ok 5037 numbers
Test #13:
score: 0
Accepted
time: 340ms
memory: 17492kb
input:
100000 100000 1 49702 2 2333 3 57831 4 12821 5 62769 6 86649 7 42954 8 30845 9 6944 10 85242 11 29311 12 5403 13 41153 14 2035 15 93153 16 81418 17 11087 18 12973 19 43286 20 9192 21 26723 22 55297 23 69360 24 78933 25 69855 26 33093 27 36813 28 99089 29 46016 30 31662 31 21406 32 91918 33 75022 34 ...
output:
116023 74250 12533 23051 52968 29149 10175 3442 19482 110017 81204 46160 87223 6212 112117 46650 8708 41872 113753 21588 42133 118956 82183 41958 50964 67881 106887 70982 61306 47670 2186 57415 113171 117211 32700 77284 106361 121708 98751 107296 66647 51878 94513 15650 34650 107171 100594 125147 30...
result:
ok 94964 numbers
Test #14:
score: 0
Accepted
time: 2676ms
memory: 17128kb
input:
100000 100000 1 51281 2 98534 3 56890 4 91069 5 13958 6 53488 7 85023 8 36325 9 53644 10 51148 11 40287 12 22074 13 71930 14 42072 15 26952 16 97057 17 38720 18 18348 19 55081 20 46329 21 6145 22 96670 23 17563 24 63818 25 33264 26 89453 27 4561 28 8807 29 90035 30 50901 31 76224 32 63425 33 64586 3...
output:
48966 34949 100005 115783 90664 101369 86978 68458 124455 60125 720 162086 197800 46796 33398 187834 19882 136944 40634 187939 207446 218823 12321 205875 63213 7354 91929 104422 44719 49354 225170 123331 90704 129455 65861 194543 456311 164926 246119 166606 10928 404670 246844 136232 51411 149969 19...
result:
ok 49756 numbers
Test #15:
score: -100
Time Limit Exceeded
input:
100000 100000 1 92615 2 88373 3 88745 4 58354 5 24241 6 70117 7 7474 8 47980 9 6849 10 9192 11 66174 12 88815 13 50287 14 60656 15 11112 16 48531 17 69958 18 53839 19 71335 20 10861 21 15521 22 67298 23 61906 24 34513 25 74665 26 31182 27 77910 28 39425 29 13475 30 29380 31 36965 32 71970 33 28150 3...