結果
問題 | No.1216 灯籠流し/Lanterns |
ユーザー | risujiroh |
提出日時 | 2020-08-30 16:03:18 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 2,580 ms / 4,500 ms |
コード長 | 6,798 bytes |
コンパイル時間 | 9,043 ms |
コンパイル使用メモリ | 459,444 KB |
実行使用メモリ | 107,816 KB |
最終ジャッジ日時 | 2024-11-15 10:42:55 |
合計ジャッジ時間 | 51,172 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,820 KB |
testcase_01 | AC | 2 ms
6,816 KB |
testcase_02 | AC | 1 ms
6,816 KB |
testcase_03 | AC | 2 ms
6,820 KB |
testcase_04 | AC | 35 ms
18,040 KB |
testcase_05 | AC | 1,416 ms
100,752 KB |
testcase_06 | AC | 76 ms
13,568 KB |
testcase_07 | AC | 1,353 ms
86,444 KB |
testcase_08 | AC | 1,196 ms
68,788 KB |
testcase_09 | AC | 485 ms
44,524 KB |
testcase_10 | AC | 529 ms
43,236 KB |
testcase_11 | AC | 197 ms
31,512 KB |
testcase_12 | AC | 31 ms
15,380 KB |
testcase_13 | AC | 242 ms
39,664 KB |
testcase_14 | AC | 93 ms
22,668 KB |
testcase_15 | AC | 183 ms
30,040 KB |
testcase_16 | AC | 147 ms
34,564 KB |
testcase_17 | AC | 1,056 ms
52,316 KB |
testcase_18 | AC | 218 ms
30,548 KB |
testcase_19 | AC | 1,563 ms
90,668 KB |
testcase_20 | AC | 556 ms
53,712 KB |
testcase_21 | AC | 249 ms
36,720 KB |
testcase_22 | AC | 1,183 ms
65,028 KB |
testcase_23 | AC | 49 ms
22,828 KB |
testcase_24 | AC | 68 ms
12,800 KB |
testcase_25 | AC | 34 ms
9,600 KB |
testcase_26 | AC | 561 ms
40,464 KB |
testcase_27 | AC | 143 ms
27,104 KB |
testcase_28 | AC | 86 ms
24,740 KB |
testcase_29 | AC | 239 ms
39,444 KB |
testcase_30 | AC | 425 ms
46,568 KB |
testcase_31 | AC | 1,037 ms
59,484 KB |
testcase_32 | AC | 380 ms
48,876 KB |
testcase_33 | AC | 76 ms
20,636 KB |
testcase_34 | AC | 1,541 ms
105,688 KB |
testcase_35 | AC | 1,881 ms
106,784 KB |
testcase_36 | AC | 2,580 ms
107,376 KB |
testcase_37 | AC | 542 ms
69,696 KB |
testcase_38 | AC | 1,635 ms
104,920 KB |
testcase_39 | AC | 1,818 ms
104,268 KB |
testcase_40 | AC | 1,758 ms
106,816 KB |
testcase_41 | AC | 1,769 ms
107,664 KB |
testcase_42 | AC | 1,768 ms
106,340 KB |
testcase_43 | AC | 1,802 ms
107,816 KB |
testcase_44 | AC | 1,816 ms
107,776 KB |
testcase_45 | AC | 1,656 ms
107,212 KB |
testcase_46 | AC | 1,641 ms
107,292 KB |
testcase_47 | AC | 1,636 ms
106,704 KB |
testcase_48 | AC | 1,648 ms
106,184 KB |
testcase_49 | AC | 1,701 ms
105,668 KB |
ソースコード
// #ifdef ONLINE_JUDGE #pragma GCC optimize("Ofast") #pragma GCC target("avx2,bmi,bmi2,lzcnt") // #endif #include <bits/extc++.h> #include <x86intrin.h> #ifndef DUMP #define DUMP(...) void(0) #endif using namespace std; struct graph { struct edge { int src, dst; int64_t cost; int operator-(int v) const { return src ^ dst ^ v; } }; int n, m; vector<edge> edges; vector<vector<pair<int, int>>> adj; graph(int _n = 0) : n(_n), m(0), adj(n) {} int add(const edge& e, bool directed = false) { edges.push_back(e); adj[e.src].emplace_back(m, e.dst); if (not directed) adj[e.dst].emplace_back(m, e.src); return m++; } }; struct dfs_forest : graph { using T = decltype(edge::cost); vector<int> root, pv, pe, sz, dep, min_dep, last, ord, in, out; vector<T> dist; int trials; dfs_forest(int _n = 0) : graph(_n), dist(n), trials(0) { for (auto p : {&root, &pv, &pe, &sz, &dep, &min_dep, &last, &in, &out}) p->assign(n, -1); } int add(const edge& e) { return graph::add(e); } void dfs(int v) { sz[v] = 1, min_dep[v] = dep[v], last[v] = trials; in[v] = size(ord), ord.push_back(v); for (auto [id, u] : adj[v]) { if (id == pe[v]) continue; if (last[u] == trials) { min_dep[v] = min(min_dep[v], dep[u]); continue; } root[u] = root[v], pv[u] = v, pe[u] = id, dep[u] = dep[v] + 1; dist[u] = dist[v] + edges[id].cost; dfs(u); sz[v] += sz[u], min_dep[v] = min(min_dep[v], min_dep[u]); } out[v] = size(ord); } void build(int r, bool clear_ord = true) { root[r] = r, pv[r] = pe[r] = -1, dep[r] = 0, dist[r] = T{}; if (clear_ord) ord.clear(); dfs(r); ++trials; } void build() { fill(begin(root), end(root), -1); for (int v = 0; v < n; ++v) if (root[v] == -1) build(v, v == 0); } int farther(int id) const { int u = edges[id].src, v = edges[id].dst; return dep[u] < dep[v] ? v : u; } bool spans(int id) const { return id == pe[farther(id)]; } bool anc(int u, int v) const { return in[u] <= in[v] and out[v] <= out[u]; } }; template <class T> struct range2d { struct bit_vector { using size_type = uint32_t; static constexpr size_type wsize = 64; static size_type rank64(uint64_t x, size_type i) { return _popcnt64(_bzhi_u64(x, i)); } #pragma pack(4) struct block_t { uint64_t bit; size_type sum; }; #pragma pack() size_type n, zeros; vector<block_t> block; bit_vector(size_type _n = 0) : n(_n), block(n / wsize + 1) {} int operator[](size_type i) const { return block[i / wsize].bit >> i % wsize & 1; } void set(size_type i) { block[i / wsize].bit |= (uint64_t)1 << i % wsize; } void build() { for (size_type j = 0; j < n / wsize; ++j) block[j + 1].sum = block[j].sum + _popcnt64(block[j].bit); zeros = rank0(n); } size_type rank0(size_type i) const { return i - rank1(i); } size_type rank1(size_type i) const { auto&& e = block[i / wsize]; return e.sum + rank64(e.bit, i % wsize); } }; struct fenwick { int n; vector<T> t; fenwick(int _n = 0) : n(_n), t(n) {} void add(int i, T val) { for (++i; i <= n; i += _blsi_u64(i)) t[i - 1] += val; } T sum(int i) const { T res = 0; for (; i; i = _blsr_u64(i)) res += t[i - 1]; return res; } T sum(int l, int r) const { return sum(r) - sum(l); } }; using key_type = int64_t; int n, lg; vector<bit_vector> bv; vector<fenwick> ft; vector<pair<key_type, key_type>> p; vector<key_type> ys; void add_point(key_type x, key_type y) { p.emplace_back(x, y); ys.push_back(y); } void build() { sort(begin(p), end(p)); p.erase(unique(begin(p), end(p)), end(p)); n = size(p); sort(begin(ys), end(ys)); ys.erase(unique(begin(ys), end(ys)), end(ys)); vector<int> a(n), na(n); for (int i = 0; i < n; ++i) a[i] = y2a(p[i].second); lg = __lg(max(*max_element(begin(a), end(a)), 1)) + 1; bv.assign(lg, n); ft.assign(lg + 1, n); for (auto h = lg; h--;) { for (int i = 0; i < n; ++i) if (a[i] >> h & 1) bv[h].set(i); bv[h].build(); array it{begin(na), begin(na) + bv[h].zeros}; for (int i = 0; i < n; ++i) *it[bv[h][i]]++ = a[i]; swap(a, na); } } int x2i(key_type x) const { pair t{x, numeric_limits<key_type>::min()}; return lower_bound(begin(p), end(p), t) - begin(p); } int y2a(key_type y) const { return lower_bound(begin(ys), end(ys), y) - begin(ys); } void add(key_type x, key_type y, T val) { assert(binary_search(begin(p), end(p), pair{x, y})); int i = lower_bound(begin(p), end(p), pair{x, y}) - begin(p); ft[lg].add(i, val); for (int h = lg; h--;) { int i0 = bv[h].rank0(i); if (bv[h][i] == 0) i = i0; else i += bv[h].zeros - i0; ft[h].add(i, val); } } T sum(int l, int r, int ub) const { if (ub >= 1 << lg) return ft[lg].sum(l, r); T res = 0; for (int h = lg; h--;) { int l0 = bv[h].rank0(l), r0 = bv[h].rank0(r); if (~ub >> h & 1) l = l0, r = r0; else { res += ft[h].sum(l0, r0); l += bv[h].zeros - l0; r += bv[h].zeros - r0; } } return res; } T sum(key_type lx, key_type rx, key_type ly, key_type ry) const { int l = x2i(lx), r = x2i(rx); return sum(l, r, y2a(ry)) - sum(l, r, y2a(ly)); } }; int main() { cin.tie(nullptr)->sync_with_stdio(false); int n, q; cin >> n >> q; dfs_forest g(n); for (int _ = n - 1; _--;) { int u, v; int64_t w; cin >> u >> v >> w; --u, --v; g.add({u, v, w}); } g.build(); struct query { int type, v; int64_t t, l; }; vector<query> queries(q); vector<range2d<int>> ds(2 * n); for (auto&& [type, v, t, l] : queries) { cin >> type >> v >> t >> l; --v; DUMP(type, v, t, l); if (type == 0) { int i = g.in[v] + n; ds[i].add_point(t + g.dist[v], g.dist[v] - l); while (i >>= 1) ds[i].add_point(t + g.dist[v], g.dist[v] - l); } } for (auto&& e : ds) if (not empty(e.p)) e.build(); for (auto&& [type, v, t, l] : queries) { if (type == 0) { int i = g.in[v] + n; ds[i].add(t + g.dist[v], g.dist[v] - l, 1); while (i >>= 1) ds[i].add(t + g.dist[v], g.dist[v] - l, 1); } else if (type == 1) { int res = 0; for (int l = g.in[v] + n, r = g.out[v] + n; l < r; l >>= 1, r >>= 1) { if (l & 1) res += ds[l++].sum(-9e18, t + g.dist[v] + 1, -9e18, g.dist[v] + 1); if (r & 1) res += ds[--r].sum(-9e18, t + g.dist[v] + 1, -9e18, g.dist[v] + 1); } cout << res << '\n'; } else assert(false); } }