이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#pragma GCC target("popcnt")
#include <bits/stdc++.h>
using u64 = std::uint64_t;
using std::vector;
using std::array;
using std::pair;
using std::tuple;
int popcount(const u64 x) {
return __builtin_popcountll(x);
}
template <class T>
int lowb(const vector<T>& vec, const T& x) {
return std::lower_bound(vec.begin(), vec.end(), x) - vec.begin();
}
class bit_vector {
array<int, 2> all;
vector<u64> block;
vector<int> accum;
public:
bit_vector() = default;
explicit bit_vector(const vector<int>& vec) {
const int n = (int)vec.size();
const int size = (n + 63) / 64;
all.fill(0);
block.resize(size + 1);
for (int i = 0; i < n; ++i) {
all[vec[i]] += 1;
block[i / 64] |= (u64)vec[i] << (i & 63);
}
accum.resize(size + 1);
for (int i = 0; i < size; ++i) {
accum[i + 1] = accum[i] + popcount(block[i]);
}
}
int count(const int x) const {
return all[x];
}
int count(const int k, const int x) const {
const u64 mask = ((u64)1 << (k & 63)) - 1;
const int one = accum[k / 64] + popcount(block[k / 64] & mask);
return x == 1 ? one : k - one;
}
int count(const int l, const int r, const int x) const {
return count(r, x) - count(l, x);
}
};
template <int Digit>
class wavelet_matrix {
array<bit_vector, Digit> bit;
public:
wavelet_matrix() = default;
explicit wavelet_matrix(const vector<int>& vec) {
const int n = (int)vec.size();
vector<int> build(n), idx(n), next(n);
std::iota(idx.begin(), idx.end(), 0);
for (int d = Digit - 1; d >= 0; --d) {
auto zero = next.begin();
auto one = next.rbegin();
for (int i = 0; i < n; ++i) {
build[i] = vec[idx[i]] >> d & 1;
(build[i] ? *one++ : *zero++) = idx[i];
}
bit[d] = bit_vector(build);
std::reverse(next.rbegin(), one);
std::swap(idx, next);
}
}
int count(int l, int r, const int x) const {
int ret = 0;
for (int d = Digit - 1; d >= 0; --d) {
const int lc = bit[d].count(l, 1);
const int rc = bit[d].count(r, 1);
if (x >> d & 1) {
l = bit[d].count(0) + lc;
r = bit[d].count(0) + rc;
} else {
ret += (rc - lc);
l -= lc;
r -= rc;
}
}
return ret + (r - l);
}
};
class point_container {
vector<int> xs, ys;
wavelet_matrix<18> matrix;
public:
point_container() = default;
explicit point_container(vector<pair<int, int>>&& vec) {
xs.reserve(vec.size());
ys.reserve(vec.size());
std::sort(vec.begin(), vec.end());
for (const auto& [x, y] : vec) {
xs.push_back(x);
ys.push_back(y);
}
std::sort(ys.begin(), ys.end());
ys.erase(std::unique(ys.begin(), ys.end()), ys.end());
vector<int> build;
build.reserve(vec.size());
for (const auto& [x, y] : vec) {
build.push_back(lowb(ys, y));
}
matrix = wavelet_matrix<18>(build);
}
int count(const int xl, const int xr, const int y) const {
return matrix.count(lowb(xs, xl), lowb(xs, xr), lowb(ys, y));
}
};
int read() {
char c = getchar_unlocked();
while (c < '0' or '9' < c) {
c = getchar_unlocked();
}
int ret = 0;
while ('0' <= c and c <= '9') {
ret = ret * 10 + (c - '0');
c = getchar_unlocked();
}
return ret;
}
void write(int x) {
static char buf[10] = {};
int i = 0;
if (x == 0) {
putchar_unlocked('0');
} else {
while (x > 0) {
buf[i++] = '0' + (x % 10);
x /= 10;
}
while (i > 0) {
putchar_unlocked(buf[--i]);
}
}
putchar_unlocked('\n');
}
int main() {
const int Q = read();
const int T = read();
int Answer = 0;
int N = 0, M = 0;
vector<int> X(Q), Y(Q), list;
vector<char> active(Q), focus(Q);
point_container P1, P2;
const auto build = [&] {
M = N;
vector<pair<int, int>> p1, p2;
p1.reserve(M);
p2.reserve(M);
for (int i = 0; i < M; ++i) {
if (active[i]) {
p1.emplace_back(X[i], Y[i]);
p2.emplace_back(X[i], Y[i] - X[i]);
}
}
P1 = point_container(std::move(p1));
P2 = point_container(std::move(p2));
for (const int i : list) {
focus[i] = false;
}
list.clear();
};
const auto add = [&](const int x, const int y) {
X[N] = x;
Y[N] = y;
active[N] = true;
focus[N] = true;
list.push_back(N);
N += 1;
};
const auto remove = [&](const int id) {
if (!focus[id]) {
focus[id] = true;
list.push_back(id);
}
active[id] = false;
};
const auto solve = [&](const int l, const int r, const int k) {
if (r - l < k) {
return 0;
}
int ret = 0;
if (M > 0) {
ret += P1.count(0, l, l + k);
ret += P2.count(l, r - k + 1, k);
}
for (const int id : list) {
if (id < M) {
if (!active[id] and ((X[id] <= l and Y[id] >= l + k) or (l <= X[id] and X[id] <= r - k and Y[id] >= X[id] + k))) {
ret -= 1;
}
} else {
if (active[id] and ((X[id] <= l and Y[id] >= l + k) or (l <= X[id] and X[id] <= r - k and Y[id] >= X[id] + k))) {
ret += 1;
}
}
}
return ret;
};
for (int q = 0; q < Q; ++q) {
if ((int)list.size() > 3500) {
build();
}
const int t = read();
if (t == 1) {
int a = read();
int b = read();
if (T == 1) {
a ^= Answer;
b ^= Answer;
}
if (a > b) {
std::swap(a, b);
}
add(a, b);
} else if (t == 2) {
remove(read() - 1);
} else {
int a = read();
int b = read();
if (T == 1) {
a ^= Answer;
b ^= Answer;
}
if (a > b) {
std::swap(a, b);
}
Answer = solve(a, b, read() - 1);
write(Answer);
}
}
return 0;
}
/*
6 1
1 1 2
3 2 4 2
1 3 5
3 2 3 1
2 1
3 0 3 1
6 0
1 3 10
1 3 5
3 6 10 6
2 1
1 3 10
3 6 4 2
*/
# | 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |