結果
問題 |
No.3189 Semifinal Stage
|
ユーザー |
|
提出日時 | 2025-06-20 22:14:46 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 371 ms / 4,000 ms |
コード長 | 5,475 bytes |
コンパイル時間 | 3,152 ms |
コンパイル使用メモリ | 289,732 KB |
実行使用メモリ | 33,940 KB |
最終ジャッジ日時 | 2025-06-20 22:15:00 |
合計ジャッジ時間 | 11,666 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 30 |
コンパイルメッセージ
main.cpp: In function ‘int main()’: main.cpp:207:8: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 207 | scanf("%d", &N); | ~~~~~^~~~~~~~~~ main.cpp:256:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 256 | scanf("%d %d", &s, &t); | ~~~~~^~~~~~~~~~~~~~~~~ main.cpp:271:8: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 271 | scanf("%d", &Q); | ~~~~~^~~~~~~~~~ main.cpp:274:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 274 | scanf("%d %d", &T[i], &X[i]); | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~
ソースコード
//https://www.spoj.com/problems/QTREE5/ //https://ei1333.hateblo.jp/entry/2019/07/09/005011 #include <bits/stdc++.h> using namespace std; template< typename SUM, typename KEY > struct LinkCutTreeSubtree { struct Node { Node *l, *r, *p; KEY key; SUM sum; bool rev; int sz; bool is_root() const { return !p || (p->l != this && p->r != this); } Node(const KEY &key, const SUM &sum) : key(key), sum(sum), rev(false), sz(1), l(nullptr), r(nullptr), p(nullptr) {} }; const SUM ident; LinkCutTreeSubtree(const SUM &ident) : ident(ident) {} Node *make_node(const KEY &key) { auto ret = new Node(key, ident); update(ret); return ret; } Node *set_key(Node *t, const KEY &key) { expose(t); t->key = key; update(t); return t; } void toggle(Node *t) { swap(t->l, t->r); t->sum.toggle(); t->rev ^= true; } void push(Node *t) { if(t->rev) { if(t->l) toggle(t->l); if(t->r) toggle(t->r); t->rev = false; } } void update(Node *t) { t->sz = 1; if(t->l) t->sz += t->l->sz; if(t->r) t->sz += t->r->sz; t->sum.merge(t->key, t->l ? t->l->sum : ident, t->r ? t->r->sum : ident); } void rotr(Node *t) { auto *x = t->p, *y = x->p; if((x->l = t->r)) t->r->p = x; t->r = x, x->p = t; update(x), update(t); if((t->p = y)) { if(y->l == x) y->l = t; if(y->r == x) y->r = t; update(y); } } void rotl(Node *t) { auto *x = t->p, *y = x->p; if((x->r = t->l)) t->l->p = x; t->l = x, x->p = t; update(x), update(t); if((t->p = y)) { if(y->l == x) y->l = t; if(y->r == x) y->r = t; update(y); } } void splay(Node *t) { push(t); while(!t->is_root()) { auto *q = t->p; if(q->is_root()) { push(q), push(t); if(q->l == t) rotr(t); else rotl(t); } else { auto *r = q->p; push(r), push(q), push(t); if(r->l == q) { if(q->l == t) rotr(q), rotr(t); else rotl(t), rotr(t); } else { if(q->r == t) rotl(q), rotl(t); else rotr(t), rotl(t); } } } } Node *expose(Node *t) { Node *rp = nullptr; for(auto *cur = t; cur; cur = cur->p) { splay(cur); if(cur->r) cur->sum.add(cur->r->sum); cur->r = rp; if(cur->r) cur->sum.erase(cur->r->sum); update(cur); rp = cur; } splay(t); return rp; } void link(Node *child, Node *parent) { expose(child); expose(parent); child->p = parent; parent->r = child; } void cut(Node *child) { expose(child); auto *parent = child->l; child->l = nullptr; parent->p = nullptr; update(child); } void evert(Node *t) { expose(t); toggle(t); push(t); } Node *lca(Node *u, Node *v) { if(get_root(u) != get_root(v)) return nullptr; expose(u); return expose(v); } Node *get_kth(Node *x, int k) { expose(x); while(x) { push(x); if(x->r && x->r->sz > k) { x = x->r; } else { if(x->r) k -= x->r->sz; if(k == 0) return x; k -= 1; x = x->l; } } return nullptr; } Node *get_root(Node *x) { expose(x); while(x->l) { push(x); x = x->l; } return x; } }; struct PQ { priority_queue< int, vector< int >, greater< int > > in, out; inline int top() { if(!in.empty()) return in.top(); return 1000000000; } inline void insert(int k) { in.emplace(k); } inline void erase(int k) { out.emplace(k); while(out.size() && in.top() == out.top()) { in.pop(); out.pop(); } } }; int main() { int N; scanf("%d", &N); struct Sum { int all; int p_len, c_len; PQ md1; Sum() : all(0), p_len(1000000000), c_len(1000000000) {} void toggle() { swap(p_len, c_len); } void merge(bool iswhite, const Sum &parent, const Sum &child) { all = parent.all + 1 + child.all; int top = md1.top(); p_len = min(child.p_len, min(top, parent.p_len) + 1 + child.all); c_len = min(parent.c_len, min(top, child.c_len) + 1 + parent.all); if(iswhite) { p_len = min(p_len, 1 + child.all); c_len = min(c_len, 1 + parent.all); } } void add(const Sum &ch) { md1.insert(ch.c_len); } void erase(const Sum &ch) { md1.erase(ch.c_len); } } e; using LCT = LinkCutTreeSubtree< Sum, bool >; LCT lct(e); vector< LCT::Node * > vv(N); for(int i = 0; i < N; i++) { vv[i] = lct.make_node(false); } vector< int > g[100000]; for(int i = 1; i < N; i++) { int s, t; scanf("%d %d", &s, &t); --s, --t; g[s].emplace_back(t); g[t].emplace_back(s); } function< void(int, int) > dfs = [&](int idx, int par) { for(auto &to : g[idx]) { if(to == par) continue; lct.link(vv[to], vv[idx]); dfs(to, idx); } }; dfs(0, -1); int Q; scanf("%d", &Q); vector< int > T(Q), X(Q); for(int i = 0; i < Q; i++) { scanf("%d %d", &T[i], &X[i]); --X[i]; --T[i]; } for(int i = 0; i < Q; i++) { if(T[i] == 1) { lct.evert(vv[X[i]]); auto ret = vv[X[i]]->sum.c_len; if(ret >= 1000000000) ret = 0; printf("%d\n", ret - 1); } else { lct.set_key(vv[X[i]], vv[X[i]]->key ^ 1); } } }