結果
問題 | No.399 動的な領主 |
ユーザー | ferin |
提出日時 | 2020-01-02 22:45:43 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 389 ms / 2,000 ms |
コード長 | 6,340 bytes |
コンパイル時間 | 2,091 ms |
コンパイル使用メモリ | 184,600 KB |
実行使用メモリ | 12,672 KB |
最終ジャッジ日時 | 2024-11-22 18:22:11 |
合計ジャッジ時間 | 7,381 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,816 KB |
testcase_02 | AC | 2 ms
6,824 KB |
testcase_03 | AC | 2 ms
6,816 KB |
testcase_04 | AC | 3 ms
6,816 KB |
testcase_05 | AC | 27 ms
6,816 KB |
testcase_06 | AC | 389 ms
12,672 KB |
testcase_07 | AC | 378 ms
12,544 KB |
testcase_08 | AC | 341 ms
12,672 KB |
testcase_09 | AC | 357 ms
12,544 KB |
testcase_10 | AC | 4 ms
6,820 KB |
testcase_11 | AC | 17 ms
6,816 KB |
testcase_12 | AC | 237 ms
12,672 KB |
testcase_13 | AC | 213 ms
12,672 KB |
testcase_14 | AC | 52 ms
12,544 KB |
testcase_15 | AC | 208 ms
12,672 KB |
testcase_16 | AC | 234 ms
12,672 KB |
testcase_17 | AC | 371 ms
12,672 KB |
testcase_18 | AC | 372 ms
12,672 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; using PII = pair<ll, ll>; #define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i) #define REP(i, n) FOR(i, 0, n) #define ALL(x) x.begin(), x.end() template<typename T> void chmin(T &a, const T &b) { a = min(a, b); } template<typename T> void chmax(T &a, const T &b) { a = max(a, b); } struct FastIO {FastIO() { cin.tie(0); ios::sync_with_stdio(0); }}fastiofastio; #ifdef DEBUG_ #include "../program_contest_library/memo/dump.hpp" #else #define dump(...) #endif const ll INF = 1LL<<60; template<typename M> class LinkCutTree { public: using T = typename M::T; using E = typename M::E; struct node { int sz; T val, sum; E lazy; node *left, *right, *par; bool rev; node() : sz(1), val(M::T0()), sum(M::T0()), lazy(M::E0()), left(nullptr), right(nullptr), par(nullptr), rev(false) {} node(T _val) : sz(1), val(_val), sum(_val), lazy(M::E0()), left(nullptr), right(nullptr), par(nullptr), rev(false) {} inline bool isRoot() const { return (!par) || (par->left != this && par->right != this); } void push() { if(lazy != M::E0()) { val = M::g(val, lazy, 1), sum = M::g(sum, lazy, sz); if(left) left->lazy = M::h(left->lazy, lazy); if(right) right->lazy = M::h(right->lazy, lazy); lazy = M::E0(); } if(rev) { swap(left, right); sum = M::s(sum); if(left) left->rev ^= true; if(right) right->rev ^= true; rev = false; } } void eval() { sz = 1, sum = val; if(left) left->push(), sz += left->sz, sum = M::f(left->sum, sum); if(right) right->push(), sz += right->sz, sum = M::f(sum, right->sum); } }; private: void rotate(node* u, bool right) { node *p = u->par, *g = p->par; if(right) { if((p->left = u->right)) u->right->par = p; u->right = p, p->par = u; } else { if((p->right = u->left)) u->left->par = p; u->left = p, p->par = u; } p->eval(), u->eval(), u->par = g; if(!g) return; if(g->left == p) g->left = u; if(g->right == p) g->right = u; g->eval(); } // uをsplay木の根にする void splay(node* u) { while(!u->isRoot()) { node *p = u->par, *gp = p->par; if(p->isRoot()) { // zig p->push(), u->push(); rotate(u, (u == p->left)); } else { gp->push(), p->push(), u->push(); bool flag = (u == p->left); if((u == p->left) == (p == gp->left)) { // zig-zig rotate(p, flag), rotate(u, flag); } else { // zig-zag rotate(u, flag), rotate(u, !flag); } } } u->push(); } // 頂点uから根へのパスをつなげる node* expose(node* u) { node* last = nullptr; for(node* v = u; v; v = v->par) { splay(v); v->right = last; v->eval(); last = v; } splay(u); return last; } void evert(node* u) { expose(u), u->rev = !(u->rev), u->push(); } bool connected(node *u, node *v) { expose(u), expose(v); return u == v || u->par; } void link(node *u, node *v) { evert(u), u->par = v; } void cut(node* u) { // uと親の辺を切る expose(u), u->left->par = nullptr, u->left = nullptr, u->eval(); } void cut(node* u, node* v) { expose(u), expose(v); if(u->isRoot()) u->par = nullptr; else v->left->par = nullptr, v->left = nullptr, v->eval(); } node* lca(node* u, node* v) { expose(u); return expose(v); } int depth(node* u) { expose(u); return u->sz - 1; } void toRoot_range(node* u, const E x) { expose(u); u->lazy = M::h(u->lazy, x), u->push(); } void range(node* u, node* v, const E x) { evert(u), expose(v); v->lazy = M::h(v->lazy, x), v->push(); } void toRoot_query(node* u) { expose(u); return u->sum; } T query(node* u, node* v) { evert(u), expose(v); return v->sum; } public: const int n; node** arr; LinkCutTree(const vector<T> &v) : n(v.size()) { arr = new node*[n]; REP(i, n) arr[i] = new node(v[i]); } // ~LinkCutTree(){ // REP(i, n) delete arr[i]; // delete[] arr; // } bool connected(int id1, int id2){ return connected(arr[id1], arr[id2]); } void link(int id1, int id2){ return link(arr[id1], arr[id2]); } void cut(int id){ return cut(arr[id]); } // uと親の辺を切る void cut(int id1, int id2){ return cut(arr[id1], arr[id2]); } int lca(int id1, int id2){ return static_cast<size_t>(lca(arr[id1], arr[id2]) - arr[0]); } void evert(int id){ return evert(arr[id]); } int depth(int id){ return depth(arr[id]); } void toRoot_range(int id, const E x){ return toRoot_range(arr[id], x); } void range(int id1, int id2, const E x){ return range(arr[id1], arr[id2], x); } T toRoot_query(int id){ return toRoot_query(arr[id]); } T query(int id1, int id2){ return query(arr[id1], arr[id2]); } }; struct sum_monoid { using T = ll; using E = ll; static T T0() { return 0; } static constexpr E E0() { return 0; } static T f(const T &x, const T &y) { return x+y; } static T g(const T &x, const E &y, int sz) { return x + y*sz; } static E h(const E &x, const E &y) { return x+y; } static T s(const T &x) { return x; } }; int main(void) { ll n; cin >> n; vector<ll> init(n, 1); LinkCutTree<sum_monoid> lct(init); REP(i, n-1) { ll u, v; cin >> u >> v; u--, v--; lct.link(u, v); } ll q, ret = 0; cin >> q; while(q--) { ll u, v; cin >> u >> v; u--, v--; ret += lct.query(u, v); lct.range(u, v, 1); } cout << ret << endl; return 0; }