백준21973 남극 탐험 작성일 2021-08-24 | In PS 문제 링크 http://icpc.me/21973 사용 알고리즘 Link/Cut Tree 시간복잡도 $O(Q \log N)$ 풀이 링크컷 트리 연습 문제입니다. 전체 코드 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145/****************************** Author: jhnah917(Justice_Hui) g++ -std=c++17 -DLOCAL ******************************/ #include <bits/stdc++.h> #define x first #define y second #define all(v) v.begin(), v.end() #define compress(v) sort(all(v)), v.erase(unique(all(v)), v.end()) #define IDX(v, x) (lower_bound(all(v), x) - v.begin()) using namespace std; using uint = unsigned; using ll = long long; using ull = unsigned long long; struct Info{ ll val; Info() : Info(0) {} Info(ll val) : val(val) {} void set(ll v){ val = v; } Info operator + (const Info &t) const { return Info(val + t.val); } }; struct Node{ Node *l, *r, *p; int sz; bool flip; Info v, sum; Node() : Node(Info()) {} Node(Info v) : v(v), sum(v), flip(false) { l = r = p = nullptr; sz = 1; } bool IsRoot() const { return !p || (this != p->l && this != p->r); } bool IsLeft() const { return p && this == p->l; } void Rotate(){ if(IsLeft()) r && (r->p = p), p->l = r, r = p; else l && (l->p = p), p->r = l, l = p; if(!p->IsRoot()) (p->IsLeft() ? p->p->l : p->p->r) = this; auto t = p; p = t->p; t->p = this; t->Update(); Update(); } void Update(){ sz = 1; sum = v; if(l) sz += l->sz, sum = sum + l->sum; if(r) sz += r->sz, sum = sum + r->sum; } void Push(){ if(flip){ swap(l, r); flip = false; if(l) l->flip ^= 1; if(r) r->flip ^= 1; } } }; void Splay(Node *x){ for(; !x->IsRoot(); x->Rotate()){ if(!x->p->IsRoot()) x->p->p->Push(); x->p->Push(); x->Push(); if(!x->p->IsRoot()) (x->IsLeft() ^ x->p->IsLeft() ? x : x->p)->Rotate(); } x->Push(); } void Access(Node *x){ Splay(x); x->r = nullptr; x->Update(); for(auto y=x; x->p; Splay(x)){ y = x->p; Splay(y); y->r = x; y->Update(); } } void Link(Node *p, Node *c){ Access(c); Access(p); c->l = p; p->p = c; c->Update(); } void Cut(Node *x){ Access(x); x->l->p = nullptr; x->l = nullptr; x->Update(); } Node* GetLCA(Node *x, Node *y){ Access(x); Access(y); Splay(x); return x->p ? x->p : x; } Node* GetRoot(Node *x){ Access(x); while(x->l) x = x->l; Splay(x); return x; } Node* GetPar(Node *x){ Access(x); if(!x->l) return nullptr; x = x->l; while(x->r) x = x->r; Splay(x); return x; } int GetDepth(Node *x){ Access(x); if(x->l) return x->l->sz; return 0; } void MakeRoot(Node *x){ Access(x); Splay(x); x->flip ^= 1; } bool IsConnect(Node *x, Node *y){ return GetRoot(x) == GetRoot(y); } void ChangeValue(Node *x, const Info val){ Access(x); x->v = val; x->Update(); } Info VertexQuery(Node *x, Node *y){ Node *l = GetLCA(x, y); Info ret = l->v; Access(x); Splay(l); if(l->r) ret = ret + l->r->sum; Access(y); Splay(l); if(l->r) ret = ret + l->r->sum; return ret; } int N, Q; Node T[30303]; int main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); cin >> N; for(int i=1,t; i<=N; i++) cin >> t, ChangeValue(T+i, t); cin >> Q; while(Q--){ string op; int a, b; cin >> op >> a >> b; if(op[0] == 'b'){ if(IsConnect(T+a, T+b)){ cout << "no" << endl; continue; } cout << "yes" << endl; MakeRoot(T+a); MakeRoot(T+b); Link(T+a, T+b); } else if(op[0] == 'p'){ ChangeValue(T+a, b); } else{ if(!IsConnect(T+a, T+b)) cout << "impossible" << endl; else cout << VertexQuery(T+a, T+b).val << endl; } } }