QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#106529 | #5249. Bandits | maspy | WA | 1019ms | 62940kb | C++23 | 30.9kb | 2023-05-18 00:18:11 | 2023-05-18 00:18:14 |
Judging History
answer
#line 1 "library/my_template.hpp"
#if defined(LOCAL)
#include <my_template_compiled.hpp>
#else
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;
template <class T>
constexpr T infty = 0;
template <>
constexpr int infty<int> = 1'000'000'000;
template <>
constexpr ll infty<ll> = ll(infty<int>) * infty<int> * 2;
template <>
constexpr u32 infty<u32> = infty<int>;
template <>
constexpr u64 infty<u64> = infty<ll>;
template <>
constexpr i128 infty<i128> = i128(infty<ll>) * infty<ll>;
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 FOR_subset(t, s) \
for (ll t = (s); t >= 0; t = (t == 0 ? -1 : (t - 1) & (s)))
#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); }
// (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, typename U>
T ceil(T x, U y) {
return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U>
T floor(T x, U y) {
return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T, typename U>
pair<T, T> divmod(T x, U y) {
T q = floor(x, y);
return {q, x - q * y};
}
template <typename T, typename U>
T SUM(const vector<U> &A) {
T sum = 0;
for (auto &&a: A) sum += a;
return sum;
}
#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) {
assert(!que.empty());
T a = que.top();
que.pop();
return a;
}
template <typename T>
T POP(vc<T> &que) {
assert(!que.empty());
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;
tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, 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;
tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, 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;
}
#endif
#line 1 "library/other/io.hpp"
// based on yosupo's fastio
#include <unistd.h>
namespace fastio {
#define FASTIO
// クラスが read(), print() を持っているかを判定するメタ関数
struct has_write_impl {
template <class T>
static auto check(T &&x) -> decltype(x.write(), std::true_type{});
template <class T>
static auto check(...) -> std::false_type;
};
template <class T>
class has_write : public decltype(has_write_impl::check<T>(std::declval<T>())) {
};
struct has_read_impl {
template <class T>
static auto check(T &&x) -> decltype(x.read(), std::true_type{});
template <class T>
static auto check(...) -> std::false_type;
};
template <class T>
class has_read : public decltype(has_read_impl::check<T>(std::declval<T>())) {};
struct Scanner {
FILE *fp;
char line[(1 << 15) + 1];
size_t st = 0, ed = 0;
void reread() {
memmove(line, line + st, ed - st);
ed -= st;
st = 0;
ed += fread(line + ed, 1, (1 << 15) - ed, fp);
line[ed] = '\0';
}
bool succ() {
while (true) {
if (st == ed) {
reread();
if (st == ed) return false;
}
while (st != ed && isspace(line[st])) st++;
if (st != ed) break;
}
if (ed - st <= 50) {
bool sep = false;
for (size_t i = st; i < ed; i++) {
if (isspace(line[i])) {
sep = true;
break;
}
}
if (!sep) reread();
}
return true;
}
template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
bool read_single(T &ref) {
if (!succ()) return false;
while (true) {
size_t sz = 0;
while (st + sz < ed && !isspace(line[st + sz])) sz++;
ref.append(line + st, sz);
st += sz;
if (!sz || st != ed) break;
reread();
}
return true;
}
template <class T, enable_if_t<is_integral<T>::value, int> = 0>
bool read_single(T &ref) {
if (!succ()) return false;
bool neg = false;
if (line[st] == '-') {
neg = true;
st++;
}
ref = T(0);
while (isdigit(line[st])) { ref = 10 * ref + (line[st++] & 0xf); }
if (neg) ref = -ref;
return true;
}
template <typename T,
typename enable_if<has_read<T>::value>::type * = nullptr>
inline bool read_single(T &x) {
x.read();
return true;
}
bool read_single(double &ref) {
string s;
if (!read_single(s)) return false;
ref = std::stod(s);
return true;
}
bool read_single(char &ref) {
string s;
if (!read_single(s) || s.size() != 1) return false;
ref = s[0];
return true;
}
template <class T>
bool read_single(vector<T> &ref) {
for (auto &d: ref) {
if (!read_single(d)) return false;
}
return true;
}
template <class T, class U>
bool read_single(pair<T, U> &p) {
return (read_single(p.first) && read_single(p.second));
}
template <size_t N = 0, typename T>
void read_single_tuple(T &t) {
if constexpr (N < std::tuple_size<T>::value) {
auto &x = std::get<N>(t);
read_single(x);
read_single_tuple<N + 1>(t);
}
}
template <class... T>
bool read_single(tuple<T...> &tpl) {
read_single_tuple(tpl);
return true;
}
void read() {}
template <class H, class... T>
void read(H &h, T &... t) {
bool f = read_single(h);
assert(f);
read(t...);
}
Scanner(FILE *fp) : fp(fp) {}
};
struct Printer {
Printer(FILE *_fp) : fp(_fp) {}
~Printer() { flush(); }
static constexpr size_t SIZE = 1 << 15;
FILE *fp;
char line[SIZE], small[50];
size_t pos = 0;
void flush() {
fwrite(line, 1, pos, fp);
pos = 0;
}
void write(const char val) {
if (pos == SIZE) flush();
line[pos++] = val;
}
template <class T, enable_if_t<is_integral<T>::value, int> = 0>
void write(T val) {
if (pos > (1 << 15) - 50) flush();
if (val == 0) {
write('0');
return;
}
if (val < 0) {
write('-');
val = -val; // todo min
}
size_t len = 0;
while (val) {
small[len++] = char(0x30 | (val % 10));
val /= 10;
}
for (size_t i = 0; i < len; i++) { line[pos + i] = small[len - 1 - i]; }
pos += len;
}
void write(const string s) {
for (char c: s) write(c);
}
void write(const char *s) {
size_t len = strlen(s);
for (size_t i = 0; i < len; i++) write(s[i]);
}
void write(const double x) {
ostringstream oss;
oss << fixed << setprecision(15) << x;
string s = oss.str();
write(s);
}
void write(const long double x) {
ostringstream oss;
oss << fixed << setprecision(15) << x;
string s = oss.str();
write(s);
}
template <typename T,
typename enable_if<has_write<T>::value>::type * = nullptr>
inline void write(T x) {
x.write();
}
template <class T>
void write(const vector<T> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) write(' ');
write(val[i]);
}
}
template <class T, class U>
void write(const pair<T, U> val) {
write(val.first);
write(' ');
write(val.second);
}
template <size_t N = 0, typename T>
void write_tuple(const T t) {
if constexpr (N < std::tuple_size<T>::value) {
if constexpr (N > 0) { write(' '); }
const auto x = std::get<N>(t);
write(x);
write_tuple<N + 1>(t);
}
}
template <class... T>
bool write(tuple<T...> tpl) {
write_tuple(tpl);
return true;
}
template <class T, size_t S>
void write(const array<T, S> val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) write(' ');
write(val[i]);
}
}
void write(i128 val) {
string s;
bool negative = 0;
if (val < 0) {
negative = 1;
val = -val;
}
while (val) {
s += '0' + int(val % 10);
val /= 10;
}
if (negative) s += "-";
reverse(all(s));
if (len(s) == 0) s = "0";
write(s);
}
};
Scanner scanner = Scanner(stdin);
Printer printer = Printer(stdout);
void flush() { printer.flush(); }
void print() { printer.write('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
printer.write(head);
if (sizeof...(Tail)) printer.write(' ');
print(forward<Tail>(tail)...);
}
void read() {}
template <class Head, class... Tail>
void read(Head &head, Tail &... tail) {
scanner.read(head);
read(tail...);
}
} // namespace fastio
using fastio::print;
using fastio::flush;
using fastio::read;
#define INT(...) \
int __VA_ARGS__; \
read(__VA_ARGS__)
#define LL(...) \
ll __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); }
#line 3 "main.cpp"
#line 2 "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 {
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; }
constexpr bool is_directed() { return directed; }
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;
}
// 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();
}
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];
}
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);
}
}
// G における頂点 V[i] が、新しいグラフで i になるようにする
Graph<T, directed> rearrange(vc<int> V) {
int n = len(V);
map<int, int> MP;
FOR(i, n) MP[V[i]] = i;
Graph<T, directed> G(n);
for (auto&& e: edges) {
if (MP.count(e.frm) && MP.count(e.to)) {
G.add(MP[e.frm], MP[e.to], e.cost);
}
}
G.build();
return G;
}
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 2 "library/graph/centroid.hpp"
// (v,w) or (v,-1)
template <typename GT>
pair<int, int> find_centroids(GT& G) {
int N = G.N;
vc<int> par(N, -1);
vc<int> V(N);
vc<int> sz(N);
int l = 0, r = 0;
V[r++] = 0;
while (l < r) {
int v = V[l++];
for (auto&& e: G[v])
if (e.to != par[v]) {
par[e.to] = v;
V[r++] = e.to;
}
}
FOR_R(i, N) {
int v = V[i];
sz[v] += 1;
int p = par[v];
if (p != -1) sz[p] += sz[v];
}
int M = N / 2;
auto check = [&](int v) -> bool {
if (N - sz[v] > M) return false;
for (auto&& e: G[v]) {
if (e.to != par[v] && sz[e.to] > M) return false;
}
return true;
};
pair<int, int> ANS = {-1, -1};
FOR(v, N) if (check(v)) {
if (ANS.fi != -1) {
ANS.se = v;
} else {
ANS.fi = v;
}
}
return ANS;
}
template <typename GT>
struct Centroid_Decomposition {
using edge_type = typename GT::edge_type;
GT& G;
int N;
vc<int> sz;
vc<int> par;
vector<int> cdep; // depth in centroid tree
bool calculated;
Centroid_Decomposition(GT& G)
: G(G), N(G.N), sz(G.N), par(G.N), cdep(G.N, -1) {
calculated = 0;
build();
}
private:
int find(int v) {
vc<int> V = {v};
par[v] = -1;
int p = 0;
while (p < len(V)) {
int v = V[p++];
sz[v] = 0;
for (auto&& e: G[v]) {
if (e.to == par[v] || cdep[e.to] != -1) continue;
par[e.to] = v;
V.eb(e.to);
}
}
while (len(V)) {
int v = V.back();
V.pop_back();
sz[v] += 1;
if (p - sz[v] <= p / 2) return v;
sz[par[v]] += sz[v];
}
return -1;
}
void build() {
assert(G.is_prepared());
assert(!G.is_directed());
assert(!calculated);
calculated = 1;
vc<pair<int, int>> st;
st.eb(0, 0);
while (!st.empty()) {
auto [lv, v] = st.back();
st.pop_back();
auto c = find(v);
cdep[c] = lv;
for (auto&& e: G[c]) {
if (cdep[e.to] == -1) { st.eb(lv + 1, e.to); }
}
}
}
public:
// vector of pairs (v, path data v)
template <typename E, typename F>
vc<vc<pair<int, E>>> collect(int root, E root_val, F f) {
vc<vc<pair<int, E>>> res = {{{root, root_val}}};
for (auto&& e: G[root]) {
int nxt = e.to;
if (cdep[nxt] < cdep[root]) continue;
vc<pair<int, E>> dat;
int p = 0;
dat.eb(nxt, f(root_val, e));
par[nxt] = root;
while (p < len(dat)) {
auto [v, val] = dat[p++];
for (auto&& e: G[v]) {
if (e.to == par[v]) continue;
if (cdep[e.to] < cdep[root]) continue;
par[e.to] = v;
dat.eb(e.to, f(val, e));
}
}
res.eb(dat);
res[0].insert(res[0].end(), all(dat));
}
return res;
}
vc<vc<pair<int, int>>> collect_dist(int root) {
auto f = [&](int x, auto e) -> int { return x + 1; };
return collect(root, 0, f);
}
// (V, H), (V[i] in G) = (i in H).
// 0,1,2... is a dfs order in H.
pair<vc<int>, Graph<typename GT::cost_type, true>> get_subgraph(int root) {
static vc<int> conv;
while (len(conv) < N) conv.eb(-1);
vc<int> V;
using cost_type = typename GT::cost_type;
vc<tuple<int, int, cost_type>> edges;
auto dfs = [&](auto& dfs, int v, int p) -> void {
conv[v] = len(V);
V.eb(v);
for (auto&& e: G[v]) {
int to = e.to;
if (to == p) continue;
if (cdep[to] < cdep[root]) continue;
dfs(dfs, to, v);
edges.eb(conv[v], conv[to], e.cost);
}
};
dfs(dfs, root, -1);
int n = len(V);
Graph<typename GT::cost_type, true> H(n);
for (auto&& [a, b, c]: edges) H.add(a, b, c);
H.build();
for (auto&& v: V) conv[v] = -1;
return {V, H};
}
};
#line 2 "library/graph/tree.hpp"
#line 4 "library/graph/tree.hpp"
// HLD euler tour をとっていろいろ。
// 木以外、非連結でも dfs 順序や親がとれる。
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 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 ELID(int v) { return 2 * LID[v] - depth[v]; }
int ERID(int v) { return 2 * RID[v] - depth[v] - 1; }
/* k: 0-indexed */
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;
}
}
// root を根とした場合の lca
int LCA_root(int u, int v, int root) {
return LCA(u, v) ^ LCA(u, root) ^ LCA(v, root);
}
int lca(int u, int v) { return LCA(u, v); }
int lca_root(int u, int v, int root) { return LCA_root(u, v, root); }
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<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;
}
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;
}
};
#line 2 "library/ds/segtree/dual_segtree.hpp"
template <typename Monoid>
struct Dual_SegTree {
using MA = Monoid;
using A = typename MA::value_type;
int n, log, size;
vc<A> laz;
Dual_SegTree() : Dual_SegTree(0) {}
Dual_SegTree(int n) { build(n); }
void build(int m) {
n = m;
log = 1;
while ((1 << log) < n) ++log;
size = 1 << log;
laz.assign(size << 1, MA::unit());
}
A get(int p) {
assert(0 <= p && p < n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
return laz[p];
}
vc<A> get_all() {
FOR(i, size) push(i);
return {laz.begin() + size, laz.begin() + size + n};
}
void apply(int l, int r, const A& a) {
assert(0 <= l && l <= r && r <= n);
if (l == r) return;
l += size, r += size;
if (!MA::commute) {
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
}
while (l < r) {
if (l & 1) all_apply(l++, a);
if (r & 1) all_apply(--r, a);
l >>= 1, r >>= 1;
}
}
private:
void push(int k) {
if (laz[k] == MA::unit()) return;
all_apply(2 * k, laz[k]), all_apply(2 * k + 1, laz[k]);
laz[k] = MA::unit();
}
void all_apply(int k, A a) { laz[k] = MA::op(laz[k], a); }
};
#line 2 "library/alg/monoid/add.hpp"
template <typename X>
struct Monoid_Add {
using value_type = X;
static constexpr X op(const X &x, const X &y) noexcept { return x + y; }
static constexpr X inverse(const X &x) noexcept { return -x; }
static constexpr X power(const X &x, ll n) noexcept { return X(n) * x; }
static constexpr X unit() { return X(0); }
static constexpr bool commute = true;
};
#line 9 "main.cpp"
void solve() {
LL(N);
Graph<ll, 0> G(N);
G.read_tree(1);
LL(Q);
using T = tuple<int, int, int>;
vc<T> query;
vvc<int> VtoQ(N), EtoQ(N - 1);
FOR(q, Q) {
STR(S);
INT(idx);
--idx;
if (S == "+") {
LL(R);
query.eb(0, idx, R);
VtoQ[idx].eb(q);
} else {
query.eb(1, idx, 0);
EtoQ[idx].eb(q);
}
}
vi ANS(Q);
// query idx, query type, idx, val
using T4 = tuple<int, int, int, int>;
auto solve = [&](Graph<ll, 1> G, vc<T4> QUERY) -> void {
ll N = G.N;
vc<int> EV(N - 1);
FOR(i, N - 1) {
auto e = G.edges[i];
EV[e.id] = e.to;
}
for (auto&& [qid, t, idx, val]: QUERY)
if (t == 1) idx = EV[idx];
vi dist(N), grp(N, 0);
vvc<int> V(N);
auto dfs = [&](auto& dfs, int v, int g, ll d) -> void {
grp[v] = g, dist[v] = d;
for (auto&& e: G[v]) dfs(dfs, e.to, g, d + e.cost);
};
for (auto&& e: G[0]) dfs(dfs, e.to, e.to, e.cost);
V[0] = {0};
FOR(v, 1, N) V[0].eb(v), V[grp[v]].eb(v);
FOR(g, N) {
sort(all(V[g]),
[&](auto& a, auto& b) -> bool { return dist[a] < dist[b]; });
}
using SEG = Dual_SegTree<Monoid_Add<int>>;
vc<SEG> seg(N);
FOR(i, N) seg[i].build(len(V[i]));
vvc<int> D(N);
FOR(g, N) for (auto&& v: V[g]) D[g].eb(dist[v]);
vc<int> IDX0(N), IDX1(N);
FOR(i, N) IDX0[V[0][i]] = i;
FOR(g, 1, N) {
FOR(i, len(V[g])) { IDX1[V[g][i]] = i; }
}
vc<int> ADD(N);
for (auto&& [qid, t, v, val]: QUERY) {
if (t == 0) {
ll x = val - dist[v];
if (x < 0) continue;
ll k = UB(D[0], x);
seg[0].apply(0, k, 1);
if (v > 0) {
int g = grp[v];
ADD[g]++;
ll k = UB(D[g], x);
seg[g].apply(0, k, 1);
}
} else {
ll ans = 0;
ans += ADD[v];
ans += seg[0].get(IDX0[v]);
int g = grp[v];
ans -= seg[g].get(IDX1[v]);
ANS[qid] += ans;
}
}
};
Centroid_Decomposition<decltype(G)> CD(G);
Tree<decltype(G)> tree(G);
vc<int> new_idx(N, -1);
FOR(root, N) {
auto [V, G1] = CD.get_subgraph(root);
FOR(i, len(V)) new_idx[V[i]] = i;
vc<T4> sub_query;
for (auto&& v: V) {
for (auto&& qid: VtoQ[v]) {
auto [a, b, c] = query[qid];
sub_query.eb(qid, 0, new_idx[v], c);
}
}
for (auto&& e: G1.edges) {
int a = V[e.frm], b = V[e.to];
int k = (tree.parent[a] == b ? tree.v_to_e(a) : tree.v_to_e(b));
for (auto&& qid: EtoQ[k]) { sub_query.eb(qid, 1, e.id, 0); }
}
FOR(i, len(V)) new_idx[V[i]] = -1;
sort(all(sub_query));
solve(G1, sub_query);
}
FOR(q, Q) {
auto [t, i, x] = query[q];
if (t == 1) print(ANS[q]);
}
}
signed main() {
solve();
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1019ms
memory: 62940kb
input:
100000 2670 75097 4080 87477 75802 1712 51835 36626 2883 19412 25923 5852 23976 19312 2520 82536 19514 2492 27160 66601 4483 99087 15088 3504 47050 58820 2964 37063 5696 9901 7717 1496 4891 79136 5448 4340 22575 81285 9289 96280 3803 9877 41980 32139 2855 44236 64938 3298 5983 99947 9666 95856 62545...
output:
0 0 0 2 2 5 2 2 3 4 4 7 8 9 11 10 14 12 12 10 11 10 10 9 10 11 11 9 15 11 14 13 14 16 11 17 15 13 15 14 14 20 15 20 22 22 20 17 23 23 24 29 24 26 30 31 36 28 37 39 35 34 45 39 46 45 43 46 42 49 44 50 43 47 52 50 49 57 51 56 61 58 68 66 69 69 61 63 67 63 72 74 78 72 73 78 77 73 85 76 86 82 85 76 82 8...
result:
ok 50000 lines
Test #2:
score: 0
Accepted
time: 643ms
memory: 57640kb
input:
100000 30038 18547 1594 65857 34063 4575 36600 72585 2328 99199 77595 1590 64257 48199 589 72301 40302 5083 69474 97536 606 60079 67381 9331 65982 39033 205 84122 65285 8508 18167 44905 3704 93490 94986 5941 27155 46374 6616 36232 62969 2212 79807 68652 7199 87352 59101 6880 94571 53224 3552 63610 8...
output:
0 1 3 3 3 3 4 6 10 10 12 14 14 16 18 19 19 19 19 22 22 23 23 23 23 24 25 26 26 26 26 26 26 28 31 31 31 31 31 34 34 36 40 41 41 42 42 42 42 42 44 44 44 47 48 48 48 48 48 48 48 48 48 49 50 50 53 54 54 55 55 56 56 56 56 56 59 62 62 62 62 62 62 62 62 62 62 63 65 67 69 69 69 73 73 73 74 76 76 76 76 76 79...
result:
ok 50000 lines
Test #3:
score: -100
Wrong Answer
time: 858ms
memory: 58956kb
input:
100000 61878 94907 27495452 40498 66053 163324081 9987 91760 269034612 88613 6169 634714395 87422 83687 263182872 22328 64374 595886322 57437 38976 201931120 75020 26926 516189886 88639 96262 269100132 88285 44915 173237252 88407 91931 174315082 12843 50312 641940581 13297 52746 120211351 89089 4638...
output:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
result:
wrong answer 41st lines differ - expected: '0', found: '1'