結果
問題 | No.772 Dynamic Distance Sum |
ユーザー | kriii |
提出日時 | 2018-12-21 11:00:18 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 5,653 bytes |
コンパイル時間 | 801 ms |
コンパイル使用メモリ | 81,100 KB |
実行使用メモリ | 52,480 KB |
最終ジャッジ日時 | 2024-09-25 09:17:41 |
合計ジャッジ時間 | 6,051 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,944 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 1 ms
6,944 KB |
testcase_04 | RE | - |
testcase_05 | RE | - |
testcase_06 | RE | - |
testcase_07 | RE | - |
testcase_08 | RE | - |
testcase_09 | RE | - |
testcase_10 | RE | - |
testcase_11 | RE | - |
testcase_12 | RE | - |
testcase_13 | RE | - |
testcase_14 | RE | - |
testcase_15 | RE | - |
testcase_16 | RE | - |
testcase_17 | RE | - |
testcase_18 | RE | - |
testcase_19 | RE | - |
testcase_20 | AC | 740 ms
40,448 KB |
testcase_21 | RE | - |
testcase_22 | RE | - |
testcase_23 | RE | - |
testcase_24 | RE | - |
testcase_25 | RE | - |
testcase_26 | RE | - |
testcase_27 | RE | - |
testcase_28 | RE | - |
testcase_29 | RE | - |
ソースコード
#include <stdio.h> #include <algorithm> #include <vector> #include <set> #include <map> using namespace std; struct Node{ Node(int weight_ = 1, int len_ = 0) { left = right = parent = nullptr; weight[0] = weight_; weight[1] = len_; size[0] = weight[0]; size[1] = weight[1]; hSize = 0; sum[0] = sum[1] = hSum = 0; reverse = false; } ~Node() { makeRoot(); if (right) right->parent = nullptr; for (auto &p : hNode) p.second->parent = nullptr; } Node *left, *right, *parent; long long weight[2], size[2], hSize, sum[2], hSum; bool reverse; set<pair<int, Node*> > hNode; // loser. bool isRoot(); void propagate(); void update(); void rotate(); void splay(); Node* access(); void hidePath(); void chainPath(Node *node); void makeRoot(); void link(Node *node); void cut(); void changeWeight(int weight); Node* findCenter(); }; struct LinkCutTree { LinkCutTree(){} LinkCutTree(int size) { nodeList.resize(size); for (int i=0;i<size;i++) nodeList[i] = new Node; } vector<Node*> nodeList; void addNode(int weight = 1, int len = 0) { nodeList.emplace_back(new Node(weight, len)); } Node* getNode(int i) { if (0 <= i && i < nodeList.size()) return nodeList[i]; return nullptr; } }; bool Node::isRoot() { return this == nullptr || parent == nullptr || (parent->left != this && parent->right != this); } void Node::propagate() { if (reverse){ swap(left, right); swap(sum[0],sum[1]); if (left) left->reverse = !left->reverse; if (right) right->reverse = !right->reverse; reverse = false; } } void Node::update() { size[0] = weight[0] + hSize; size[1] = weight[1]; sum[0] = sum[1] = hSum; long long psum[2] = {size[0],size[0]}, qsum[2] = {size[1],size[1]}; if (left){ size[0] += left->size[0]; size[1] += left->size[1]; psum[1] += left->size[0]; qsum[0] += left->size[1]; } if (right){ size[0] += right->size[0]; size[1] += right->size[1]; psum[0] += right->size[0]; qsum[1] += right->size[1]; } for (int k=0;k<2;k++){ if (left) sum[k] += left->sum[k^left->reverse]; if (right) sum[k] += right->sum[k^right->reverse]; sum[k] += psum[k] * qsum[k]; } } void Node::rotate() { if (isRoot()) return; Node *up = parent; up->propagate(); propagate(); Node *jump = up->parent; up->parent = this; Node *down = nullptr; if (up->left == this){ up->left = down = right; right = up; } else{ up->right = down = left; left = up; } if (down) down->parent = up; parent = jump; if (jump){ int sz = up->size[0]; auto I = jump->hNode.find({sz, up}); if (I != jump->hNode.end()){ jump->hNode.erase(I); jump->hNode.insert({sz, this}); } else if (jump->left == up) jump->left = this; else if (jump->right == up) jump->right = this; } up->update(); update(); } void Node::splay() { propagate(); while (!isRoot()){ Node *up = parent; if (!up->isRoot()){ Node *jump = up->parent; if ((this == up->left) ^ (up == jump->left)) rotate(); else up->rotate(); } rotate(); } } Node* Node::access() { hidePath(); Node* last = this; while (parent){ last = parent; parent->chainPath(this); splay(); } return last; } void Node::hidePath() { splay(); if (right && right->parent == this){ hSize += right->size[0]; hSum += right->sum[right->reverse]; hNode.insert({right->size[0], right}); right = nullptr; update(); } } void Node::chainPath(Node *node) { hidePath(); if (node && node->parent == this && left != node){ right = node; hSize -= right->size[0]; hSum -= right->sum[right->reverse]; hNode.erase({right->size[0], right}); update(); } } void Node::makeRoot() { access(); reverse = !reverse; propagate(); } void Node::link(Node *node) { if (!node) return; makeRoot(); access(); node->access(); left = node; node->parent = this; update(); } void Node::cut() { if (!parent) return; access(); if (left){ left->parent = nullptr; left = nullptr; } splay(); } void Node::changeWeight(int weight_) { makeRoot(); weight[0] = weight_; update(); } Node* Node::findCenter() { makeRoot(); int full = size[0]; if (full == 0) return this; int half = full / 2; Node *n = this; while (true){ n->propagate(); if (n->left){ if (full - n->size[0] + n->left->size[0] > half){ n = n->left; continue; } } if (n->right){ if (n->right->size[0] > half){ n = n->right; continue; } } if (!n->hNode.empty()){ auto I = n->hNode.end(); --I; if (I->first > half){ n->splay(); n = I->second; continue; } } break; } n->makeRoot(); return n; } int main() { int N,Q; scanf ("%d %d",&N,&Q); LinkCutTree lct(N); map<pair<int, int>, Node *> edge; int enc = 0; while (Q--){ int o; scanf ("%d",&o); if (o == 1){ int x,y,c; scanf ("%d %d %d",&x,&y,&c); x = (x - 1 + enc) % N; y = (y - 1 + enc) % N; if (x > y) swap(x,y); Node *e = new Node(0,c); Node *p = lct.getNode(x); Node *q = lct.getNode(y); p->access(); Node *t = q->access(); if (t == p->access()){ return 1; } p->link(e); q->link(e); edge[{x,y}] = e; } else if (o == 2){ int x,y; scanf ("%d %d",&x,&y); x = (x - 1 + enc) % N; y = (y - 1 + enc) % N; if (x > y) swap(x,y); auto I = edge.find({x,y}); if (I != edge.end()){ delete I->second; edge.erase(I); } } else if (o == 3){ int x; scanf ("%d",&x); x = (x - 1 + enc) % N; auto v = lct.getNode(x); v->changeWeight(1 - v->weight[0]); auto c = v->findCenter(); long long res = c->sum[c->reverse]; enc = (enc + res) % N; printf ("%lld\n",res); } } return 0; }