Submission #1163948

#TimeUsernameProblemLanguageResultExecution timeMemory
1163948xnqs팀들 (IOI15_teams)C++20
34 / 100
4097 ms208908 KiB
//#pragma GCC optimize("Ofast") //#pragma GCC target("avx2") #include <iostream> #include <vector> #include <queue> #include <utility> #include <algorithm> #include <random> #include <map> #include "teams.h" std::mt19937 rng(53); namespace Treap { struct Node { int key; int val; int size; int sum; int prio; Node* l; Node* r; Node(int key = 0, int val = 0): key(key), val(val), size(1), sum(val), prio(rng()), l(nullptr), r(nullptr) {} ~Node() { if (l) delete l; if (r) delete r; } }; Node* _aux_split_l = nullptr; Node* _aux_split_r = nullptr; Node* _aux_merge = nullptr; inline int GetNodeSize(Node* node) { if (!node) { return 0; } return node->size; } inline int GetNodeSum(Node* node) { if (!node) { return 0; } return node->sum; } inline void UpdateNode(Node* node) { node->size = 1; node->sum = node->val; if (node->l) { node->size += node->l->size; node->sum += node->l->sum; } if (node->r) { node->size += node->r->size; node->sum += node->r->sum; } } void SplitDriver(Node* node, int key) { if (!node) { _aux_split_l = _aux_split_r = nullptr; return; } if (key-GetNodeSize(node->l)-1>=0) { SplitDriver(node->r,key-GetNodeSize(node->l)-1); node->r = _aux_split_l; _aux_split_l = node; UpdateNode(node); } else { SplitDriver(node->l,key); node->l = _aux_split_r; _aux_split_r = node; UpdateNode(node); } } void MergeDriver(Node* a, Node* b) { if (!a) { _aux_merge = b; return; } if (!b) { _aux_merge = a; return; } if (a->prio > b->prio) { MergeDriver(a->r,b); a->r = _aux_merge; _aux_merge = a; UpdateNode(a); } else { MergeDriver(a,b->l); b->l = _aux_merge; _aux_merge = b; UpdateNode(b); } } inline std::pair<Node*, Node*> Split(Node* node, int key) { SplitDriver(node, key); return {_aux_split_l, _aux_split_r}; } inline Node* Merge(Node* a, Node* b) { MergeDriver(a, b); return _aux_merge; } int LowerBound(Node* node, int val, int skipped = 0) { if (!node) { return 0x3f3f3f3f; } int node_key = skipped + GetNodeSize(node->l); if (node->key >= val) { return std::min(node_key, LowerBound(node->l, val, skipped)); } else { return LowerBound(node->r, val, node_key+1); } } int UpperBound(Node* node, int val, int skipped = 0) { if (!node) { return 0x3f3f3f3f; } int node_key = skipped + GetNodeSize(node->l); if (node->key > val) { return std::min(node_key, UpperBound(node->l, val, skipped)); } else { return UpperBound(node->r, val, node_key+1); } } Node* Insert(Node*& node, int pos, int key, int val) { if (!node) { return node = new Node(key, val); } auto trees = Split(node, pos); return Merge(Merge(trees.first, new Node(key, val)), trees.second); } int RangeSumQuery(Node*& node, int l, int r) { if (!node) { return 0; } if (l>r) { return 0; } auto trees = Split(node, l); auto trees_right = Split(trees.second, r-l+1); int ret = Treap::GetNodeSum(trees_right.first); node = Merge(Merge(trees.first,trees_right.first),trees_right.second); return ret; } }; // namespace Treap const int BLK_SIZE = 169; int x; Treap::Node* tree[500005]; std::vector<std::pair<int,int>> segments; void tree_insert(int px, int py, int val) { while (px <= x) { int pos = std::min(Treap::GetNodeSize(tree[px]), Treap::LowerBound(tree[px], py)); tree[px] = Treap::Insert(tree[px], pos, py, val); px += px&-px; } } int tree_query(int pos, int l, int r) { int ret = 0; while (pos > 0) { int le = std::min(Treap::GetNodeSize(tree[pos]), Treap::LowerBound(tree[pos], l)); int ri = std::min(Treap::GetNodeSize(tree[pos]), Treap::UpperBound(tree[pos], r))-1; if (le==Treap::GetNodeSize(tree[pos])) { pos ^= pos&-pos; continue; } ret += Treap::RangeSumQuery(tree[pos],le,ri); pos ^= pos&-pos; } return ret; } int tree_query(int i1, int i2, int j1, int j2) { return tree_query(i2,j1,j2) - tree_query(i1-1,j1,j2); } void init(int N, int A[], int B[]) { x = N; for (int i = 0; i < x; i++) { tree_insert(A[i],B[i],1); segments.emplace_back(A[i], B[i]); } std::sort(segments.begin(),segments.end(),[](const std::pair<int,int>& a, const std::pair<int,int>& b) { return a.first < b.first; }); //std::cout << tree_query(1,1,x,1,2,2,4) << "\n"; //std::cout << tree_query(1,1,x,1,x,1,x) << "\n"; } int can(int qsz, int qarr[]) { std::sort(qarr,qarr+qsz); if (qsz > BLK_SIZE || x <= BLK_SIZE) { std::priority_queue<int, std::vector<int>, std::greater<int>> pq; int scanline = 0; for (int i = 0; i < qsz; i++) { while (scanline < segments.size() && segments[scanline].first <= qarr[i]) { pq.emplace(segments[scanline].second); ++scanline; } while (!pq.empty()&&pq.top()<qarr[i]) { pq.pop(); } int count = 0; while (!pq.empty()&&count<qarr[i]) { ++count; pq.pop(); } if (count != qarr[i]) { return 0; } } return 1; } else { std::map<int,int> freq; std::vector<int> distinct; for (int i = 0; i < qsz; i++) { ++freq[qarr[i]]; if (i+1<qsz&&qarr[i]==qarr[i+1]) { continue; } distinct.emplace_back(qarr[i]); } std::vector<std::tuple<int,int,int>> updates; int ret = 1; for (int i = 0; i < distinct.size(); i++) { int target = 1LL * freq[distinct[i]] * distinct[i]; for (int j = i; j < distinct.size() && target > 0; j++) { int le = 1; int ri = ((j+1<distinct.size()) ? distinct[j+1]-1 : x); int add = std::min(target, tree_query(1,distinct[i],distinct[i],ri)); target -= add; updates.emplace_back(1,ri,-add); tree_insert(1,ri,-add); } if (target != 0) { //std::cout << i << "\n"; ret = 0; break; } } for (const auto& [a, b, c] : updates) { tree_insert(a,b,-c); } return ret; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...