QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#455631 | #8781. Element-Wise Comparison | mendicillin2# | ML | 0ms | 3800kb | C++20 | 8.3kb | 2024-06-26 16:58:02 | 2024-06-26 16:58:02 |
Judging History
answer
#include <bits/stdc++.h>
#include <ranges>
using namespace std;
template <class T> using Vec = vector<T>;
namespace copied {
using ull = unsigned long long;
// Reference: https://judge.yosupo.jp/submission/76542
// NOT INITIALISED BY DEFAULT! call .clear to zero all bits
template <int N> class Bitset {
private:
constexpr static ull LM = (1ull << 32) - 1;
constexpr static ull FM = ~0ull;
constexpr static int H = (N + 63) >> 6;
array<ull, H> bits;
void clearHighBits() {
if constexpr (N & 63) bits[H - 1] &= ~(FM << (N & 63));
}
public:
Bitset() {}
void clear() {
for (ull& v : bits) v = 0;
}
void set() {
for (ull& v : bits) v = FM;
clearHighBits();
}
void flip() {
for (ull& v : bits) v = ~v;
clearHighBits();
}
bool get(int i) const { return bits[i >> 6] & (1ull << (i & 63)); }
void set(int i, ull v) {
bits[i >> 6] = (bits[i >> 6] & ~(1ull << (i & 63))) | (v << (i & 63));
}
void setZero(int i) { bits[i >> 6] &= ~(1ull << (i & 63)); }
void setOne(int i) { bits[i >> 6] |= 1ull << (i & 63); }
// Sets bit[a + i] = v[i] for i \in [0, b-a]. Must have 0 <= a <= b < min(a
// + 64, N)
void setRange(int a, int b, ull v) {
int j = (a >> 6), r = (a & 63), len = b - a + 1;
ull mask = FM >> (64 - len);
bits[j] = (bits[j] & ~(mask << r)) | (v << r);
if ((b >> 6) > j)
bits[j + 1] = (bits[j + 1] & ~(mask >> (64 - r))) | (v >> (64 - r));
}
// Returns v s.t. v[i] = bit[a + i] for i \in [0, b-a]. Must have 0 <= a <=
// b < min(a + 64, N)
ull getRange(int a, int b) const {
int j = (a >> 6), r = (a & 63), len = b - a + 1;
ull mask = FM >> (64 - len);
if ((b >> 6) <= j) return (bits[j] >> r) & mask;
return ((bits[j] >> r) | (bits[j + 1] << (64 - r))) & mask;
}
// Returns minimum i \in [a, b] such that bits[i] = 1, or b + 1 if none
// exist
int findNext(int a, int b = N - 1) const {
if (a > b) return b + 1;
int j = (a >> 6);
ull tmp = bits[j] >> (a & 63);
if (tmp != 0) return min(b + 1, a + __builtin_ctzll(tmp));
for (++j; (j << 6) <= b; ++j) {
if (bits[j]) return min(b + 1, (j << 6) + __builtin_ctzll(bits[j]));
}
return b + 1;
}
// Returns maximum i \in [a, b] such that bits[i] = 1, or a - 1 if none
// exist
int findPrev(int b, int a = 0) const {
if (b < a) return a - 1;
int j = (b >> 6);
ull tmp = bits[j] << (63 - (b & 63));
if (tmp != 0) return max(a - 1, b - __builtin_clzll(tmp));
for (--j; ((j + 1) << 6) > a; --j) {
if (bits[j])
return max(a - 1, (j << 6) + 63 - __builtin_clzll(bits[j]));
}
return a - 1;
}
// Counts set bits in range [a, b]
int count(int a = 0, int b = N - 1) const {
int res = 0;
if (a & 63)
res -= __builtin_popcountll(bits[a >> 6] << (64 - (a & 63)));
if ((b + 1) & 63)
res -= __builtin_popcountll(bits[b >> 6] >> ((b + 1) & 63));
for (int j = (a >> 6); j <= (b >> 6); ++j)
res += __builtin_popcountll(bits[j]);
return res;
}
bool operator==(const Bitset<N>& rhs) const {
for (int i = 0; i < H; ++i) {
if (bits[i] != rhs.bits[i]) return false;
}
return true;
}
bool operator<(const Bitset<N>& rhs) const {
for (int i = 0; i < H; ++i) {
if (bits[i] != rhs.bits[i]) return bits[i] < rhs.bits[i];
}
return false;
}
Bitset<N> operator~() const {
Bitset<N> res;
for (int i = 0; i < H; ++i) res.bits[i] = ~bits[i];
res.clearHighBits();
return res;
}
Bitset<N> operator<<(int d) const {
Bitset<N> res;
int s = min(d >> 6, H);
int r = d & 63;
for (int i = 0; i < s; ++i) res.bits[i] = 0;
if (r == 0)
for (int i = s; i < H; ++i) res.bits[i] = bits[i - s];
else {
if (s < H) res.bits[s] = bits[0] << r;
for (int i = s + 1; i < H; ++i)
res.bits[i] =
(bits[i - s] << r) | (bits[i - 1 - s] >> (64 - r));
}
res.clearHighBits();
return res;
}
Bitset<N> operator>>(int d) const {
Bitset<N> res;
int s = min(d >> 6, H);
int r = d & 63;
for (int i = H - 1; i >= H - s; ++i) res.bits[i] = 0;
if (r == 0)
for (int i = H - 1 - s; i >= 0; --i) res.bits[i] = bits[i + s];
else {
if (s < H) res.bits[H - 1 - s] = bits[H - 1] >> r;
for (int i = H - 2 - s; i >= 0; --i)
res.bits[i] =
(bits[i + s] >> r) | (bits[i + 1 + s] << (64 - r));
}
return res;
}
Bitset<N> operator|(const Bitset& rhs) const {
Bitset<N> res;
for (int i = 0; i < H; ++i) res.bits[i] = bits[i] | rhs.bits[i];
return res;
}
Bitset<N> operator&(const Bitset& rhs) const {
Bitset<N> res;
for (int i = 0; i < H; ++i) res.bits[i] = bits[i] & rhs.bits[i];
return res;
}
Bitset<N> operator^(const Bitset& rhs) const {
Bitset<N> res;
for (int i = 0; i < H; ++i) res.bits[i] = bits[i] ^ rhs.bits[i];
return res;
}
Bitset operator+(const Bitset& rhs) const {
Bitset<N> res;
uint8_t carry = 0;
for (int i = H - 1; i >= 0; --i)
carry = _addcarry_u64(carry, bits[i], rhs.bits[i], res.bits[i]);
return res;
}
Bitset operator-(const Bitset& rhs) const {
Bitset<N> res;
uint8_t borrow = 0;
for (int i = H - 1; i >= 0; --i)
borrow = _subborrow_u64(borrow, bits[i], rhs.bits[i], res.bits[i]);
return res;
}
};
} // namespace copied
template <class T, class F> struct QueueAggregation {
const F f;
const T e;
Vec<T> as, bs, ae, be;
T vs, ve;
QueueAggregation(F f_, T e_) : f(f_), e(e_), vs(e), ve(e) {}
void push_s(const T& x) { as.push_back(x), bs.push_back(vs = f(x, vs)); }
void push_e(const T& x) { ae.push_back(x), be.push_back(ve = f(ve, x)); }
void reduce() {
while (!ae.empty()) {
push_s(std::move(ae.back())), ae.pop_back();
}
be.clear();
ve = e;
}
bool empty() const { return as.empty() && ae.empty(); }
int size() const { return int(as.size() + ae.size()); }
void push(const T& x) {
if (as.empty()) {
push_s(std::move(x)), reduce();
} else {
push_e(std::move(x));
}
}
void pop() {
assert(!empty());
if (as.empty()) reduce();
as.pop_back(), bs.pop_back();
vs = (bs.empty() ? e : bs.back());
}
T prod() const { return f(vs, ve); }
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(20);
int N, M;
cin >> N >> M;
auto P = Vec<int>(N);
for (int& a : P) {
cin >> a;
a--;
}
auto invP = Vec<int>(N);
using views::iota, views::reverse;
for (int i : iota(0, N)) {
invP[P[i]] = i;
}
constexpr int MAXN = 50010;
using Bitset = copied::Bitset<MAXN>;
auto larger = Bitset{};
larger.clear();
auto mat = Vec<Bitset>(N); // mat[i][d] := [P[i] < P[i + d]]
for (int p : iota(0, N) | reverse) {
int i = invP[p];
mat[i] = larger >> i;
larger.setOne(i);
}
// auto qa = QueueAggregation(
// [](const Bitset& l, const Bitset& r) { return l & r; }, all_set);
// int64_t ans = 0;
// for (int st = 0, en = 0; st + M <= N; st++) {
// while (en - st < M) {
// qa.push(std::move(mat[en]));
// en++;
// }
// ans += int(qa.prod().count());
// qa.pop();
// }
// cout << ans << '\n';
int64_t ans = 0;
auto suffix = Vec<Bitset>(M + 1);
suffix[0].set();
auto prefix = Bitset{};
for (int l = 0; l + M <= N; l += M) {
for (int i = 0; i < M; i++) {
suffix[i + 1] = suffix[i] & mat[l + M - 1 - i];
}
prefix.set();
for (int i = 0; i < M; i++) {
ans += int((prefix & suffix[M - i]).count());
if (l + M + i == N) break;
prefix = prefix & mat[l + M + i];
}
}
cout << ans << '\n';
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3664kb
input:
5 3 5 2 1 3 4
output:
0
result:
ok answer is '0'
Test #2:
score: 0
Accepted
time: 0ms
memory: 3520kb
input:
5 2 3 1 4 2 5
output:
2
result:
ok answer is '2'
Test #3:
score: 0
Accepted
time: 0ms
memory: 3508kb
input:
4 2 1 2 3 4
output:
3
result:
ok answer is '3'
Test #4:
score: 0
Accepted
time: 0ms
memory: 3800kb
input:
4 2 4 3 2 1
output:
0
result:
ok answer is '0'
Test #5:
score: 0
Accepted
time: 0ms
memory: 3788kb
input:
1 1 1
output:
0
result:
ok answer is '0'
Test #6:
score: -100
Memory Limit Exceeded
input:
50000 2 44045 29783 5389 7756 44022 45140 21967 5478 10868 49226 21775 31669 49836 13511 46116 14229 27206 31168 37389 3158 10658 41154 14635 18526 40540 6451 23197 46719 30593 13517 8604 46666 39189 43746 12778 3684 3194 36979 43020 14652 19549 31178 17144 27177 44336 2849 40220 11751 41993 32209 4...