# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|
1163948 | | xnqs | 팀들 (IOI15_teams) | C++20 | | 4097 ms | 208908 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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |