QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#338342 | #7108. Couleur | Lain | ML | 1ms | 3544kb | C++23 | 6.3kb | 2024-02-25 20:44:55 | 2024-02-25 20:44:56 |
Judging History
answer
#include "bits/stdc++.h"
using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
// Source: Me
// Tested on: ???
struct PersistentSegTree {
struct SegTreeNode {
SegTreeNode *l, *r; // Children
// Node values
int sum = 0;
SegTreeNode(int val = 0) : l(nullptr), r(nullptr), sum(val) {}
SegTreeNode(SegTreeNode* l, SegTreeNode* r) : l(l), r(r), sum(0) {
if (l) sum += l->sum;
if (r) sum += r->sum;
}
};
vector<SegTreeNode*> roots; // History
int L, R; // Bounds
PersistentSegTree(int tl, int tr) : L(tl), R(tr) {
roots.push_back(build(tl, tr));
}
int size() { return (int)roots.size(); }
// Get node from history
SegTreeNode*& operator[](int idx) {
assert(idx < roots.size());
return roots[idx];
}
// Build segtree
SegTreeNode* build(int tl, int tr) {
if (tl == tr) return new SegTreeNode(0);
int tm = (tl + tr) / 2;
return new SegTreeNode(build(tl, tm), build(tm + 1, tr));
}
// Query current node for range [l,r]
int query(int l, int r) { return query(roots.back(), l, r, L, R); }
// Query node ind for range [l,r]
int query(int ind, int l, int r) { return query(roots[ind], l, r, L, R); }
int query(SegTreeNode* v, int l, int r, int tl, int tr) {
if (l > r) return 0;
if (l == tl && r == tr) return v->sum;
int tm = (tl + tr) / 2;
return query(v->l, l, min(r, tm), tl, tm) +
query(v->r, max(l, tm + 1), r, tm + 1, tr);
}
// Point update position pos to value val
void update(int pos, int val) {
roots.push_back(update(roots.back(), pos, val, L, R));
}
SegTreeNode* update(SegTreeNode* v, int pos, int val, int tl, int tr) {
if (tl == tr) return new SegTreeNode(v->sum + val);
int tm = (tl + tr) / 2;
if (pos <= tm)
return new SegTreeNode(update(v->l, pos, val, tl, tm), v->r);
else
return new SegTreeNode(v->l, update(v->r, pos, val, tm + 1, tr));
}
};
// Source: Lain
// Tested on: https://judge.yosupo.jp/problem/point_add_range_sum
//
// Implementation of a Fenwick Tree. can be used to make
// a order-statistics tree.
template <typename T>
struct Fenwick {
public:
Fenwick() = default;
Fenwick(int n) : n(n), tree(n + 1, 0) {}
Fenwick(const vector<T>& build) : Fenwick(build.size()) {
for (int i = 1; i <= n; i++) {
tree[i] = build[i - 1];
for (int k = (i & -i) >> 1; k > 0; k >>= 1) tree[i] += tree[i - k];
}
}
void add(int pos, const T& change) {
assert(pos < n);
for (int i = pos + 1; i <= n; i += (i & -i)) tree[i] += change;
}
T query(int r) {
assert(r < n);
T ret = 0;
for (int i = r + 1; i > 0; i -= (i & -i)) ret += tree[i];
return ret;
}
T query(int l, int r) {
return (l == 0) ? query(r) : query(r) - query(l - 1);
}
// Returns the largest p in [0,tn] such that query(p) <= sum
int find_last_prefix(T sum) {
if (sum < 0) return -1;
int prefix = 0;
for (int k = 31 - __builtin_clz(n); k >= 0; k--) {
if (prefix + (1 << k) <= n && tree[prefix + (1 << k)] <= sum) {
prefix += 1 << k;
sum -= tree[prefix];
}
}
return prefix;
}
private:
size_t n;
vector<T> tree;
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int tt;
cin >> tt;
while(tt--) {
int n;
cin >> n;
vi a(n);
for (auto&x : a) cin >> x, x--;
vector<int64_t> p(n);
for (auto& x : p) cin >> x;
int64_t ans = 0;
Fenwick<int> T(n);
PersistentSegTree PT(0, n-1);
for (int i = 0; i < n; i++) {
if (a[i]+1 <= n-1) {
ans += T.query(a[i]+1, n-1);
}
T.add(a[i], 1);
PT.update(a[i], 1);
}
for (int i =0; i < n; i++) {
T.add(a[i], -1);
}
set<array<int64_t,3>> segments;
multiset<int64_t> all_values;
all_values.insert(ans);
segments.insert({0, n-1, ans});
rep(i, 0, sz(p)) {
int64_t ans = *all_values.rbegin();
cout << ans << " \n"[i+1 == sz(p)];
int rem = p[i]^ans;
rem--;
auto it = segments.upper_bound({rem, n+10});
it--; // segment now contains rem
auto [l, r, val] = *it;
segments.erase(it);
all_values.erase(all_values.find(val));
// remove influence of rem
if (rem != r && a[rem] - 1 >= 0) {
// how many values are < a[rem] in range (rem+1, r)?
val -= PT.query(r+1, 0, a[rem] - 1) - PT.query(rem+1, 0, a[rem] - 1);
}
if (rem != l && a[rem]+1 <= n-1) {
// how many values are > a[rem] in range (l, rem-1)
val -= PT.query(rem, a[rem] + 1, n-1) - PT.query(l, a[rem] + 1, n-1);
}
if (rem-l <= r-rem) {
// iterate on the left side
int64_t left_sum = 0;
rep(j, l, rem) {
if (a[j] -1 >= 0) {
val -= PT.query(r+1, 0, a[j] - 1) - PT.query(rem+1, 0, a[j] - 1);
}
T.add(a[j], 1);
if (a[j] + 1 <= n-1) {
left_sum += T.query(a[j]+1, n-1);
}
}
rep(j, l, rem) {
T.add(a[j], -1);
}
if (l < rem) {
segments.insert({l, rem-1, left_sum});
all_values.insert(left_sum);
}
if (r > rem) {
segments.insert({rem+1, r, val-left_sum});
all_values.insert(val - left_sum);
}
} else {
// iterate on the right side
int64_t right_sum = 0;
rep(j, rem+1, r+1) {
if (a[j] + 1 <= n-1) {
val -= PT.query(rem, a[j] + 1, n-1) - PT.query(l, a[j] + 1, n-1);
}
T.add(a[j], 1);
if (a[j] + 1 <= n-1) {
right_sum += T.query(a[j]+1, n-1);
}
}
rep(j, rem+1, r+1) {
T.add(a[j], -1);
}
if (l < rem) {
segments.insert({l, rem-1, val - right_sum});
all_values.insert(val - right_sum);
}
if (r > rem) {
segments.insert({rem+1, r, right_sum});
all_values.insert(right_sum);
}
}
}
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3544kb
input:
3 5 4 3 1 1 1 5 4 5 3 1 10 9 7 1 4 7 8 5 7 4 8 21 8 15 5 9 2 4 5 10 6 15 4 8 8 1 12 1 10 14 7 14 2 9 13 10 3 37 19 23 15 7 2 10 15 2 13 4 5 8 7 10
output:
7 0 0 0 0 20 11 7 2 0 0 0 0 0 0 42 31 21 14 14 4 1 1 1 0 0 0 0 0 0
result:
ok 3 lines
Test #2:
score: -100
Memory Limit Exceeded
input:
11116 10 10 5 10 3 6 4 8 5 9 8 31 27 24 11 12 3 0 2 3 1 10 8 2 7 2 8 10 1 10 9 10 6 5 2 13 2 1 0 1 3 1 10 7 10 7 6 1 3 10 6 7 9 21 18 10 1 6 5 4 8 9 10 10 2 10 4 8 8 5 7 2 6 7 20 10 9 1 15 0 4 2 9 7 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 10 1 2 3 4 5 6 7 8 9 10 6 3 5 2 7 10 9 1 4 8 10 1 10 1 3...
output:
21 18 16 12 10 6 4 1 1 0 12 12 10 10 4 4 4 2 1 0 20 16 9 5 3 3 3 0 0 0 22 14 8 8 5 5 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 12 7 4 4 2 2 1 0 0 20 18 8 3 1 1 0 0 0 0 45 21 21 10 3 3 3 0 0 0 17 11 8 2 1 1 1 0 0 0 13 4 1 0 0 0 0 0 0 0 29 27 22 15 9 7 4 3 1 0 26 16 9 2 1 1 1 1 1 0 0 0 0 0 0 ...