QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#168262 | #7108. Couleur | ucup-team859 | RE | 0ms | 0kb | C++14 | 5.2kb | 2023-09-08 02:35:33 | 2023-09-08 02:35:35 |
answer
#include <bits/stdc++.h>
#define lsb(x) (x & (-x))
using ull = unsigned long long;
using ll = long long;
using namespace std;
struct SegTree {
struct Node {
int l = -1, r = -1;
int count = 0;
};
SegTree() {
makeNode();
}
inline int makeNode(int oldId) {
if (oldId == -1) {
return makeNode();
}
data.push_back(data[oldId]);
return (int)data.size() - 1;
}
inline int makeNode() {
data.emplace_back();
return (int)data.size() - 1;
}
int update(int id, int l, int r, int qpos) {
int newId = makeNode(id);
if (l == r) {
data[newId].count++;
} else {
int mid = (l + r) / 2;
if (qpos <= mid) data[newId].l = update(data[newId].l, l, mid, qpos);
else data[newId].r = update(data[newId].r, mid + 1, r, qpos);
data[newId].count = 0;
if (data[newId].l != -1) {
data[newId].count += data[data[newId].l].count;
}
if (data[newId].r != -1) {
data[newId].count += data[data[newId].r].count;
}
}
// cerr << newId << " " << l << " " << r << " " << data[newId].count << " --> "
// << data[data[newId].l].count << " " << data[data[newId].r].count << "\n";
return newId;
}
int query(int id, int l, int r, int ql, int qr) {
if (id == -1 || ql > qr) return 0;
if (ql <= l && r <= qr) {
return data[id].count;
} else {
int mid = (l + r) / 2;
int count = 0;
if (ql <= mid) count += query(data[id].l, l, mid, ql, qr);
if (mid < qr) count += query(data[id].r, mid + 1, r, ql, qr);
return count;
}
}
vector<Node> data;
};
int main() {
#ifdef HOME
ifstream cin("input.in");
ofstream cout("output.out");
#endif
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
for (int tt = 1; tt <= t; tt++) {
int n;
cin >> n;
vector<int> a(n + 1);
vector<vector<int>> ids(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
ids[a[i]].push_back(i);
}
SegTree st;
vector<int> roots(n + 1);
for (int i = 1; i <= n; i++) {
roots[i] = roots[i - 1];
for (auto pos : ids[i]) {
roots[i] = st.update(roots[i], 1, n, pos);
}
}
auto Get = [&](int l, int r, int low, int high) {
if (low > high) return 0;
return st.query(roots[high], 1, n, l, r) - st.query(roots[low - 1], 1, n, l, r);
};
ll answer = 0;
for (int i = 1; i <= n; i++) {
answer += Get(1, i - 1, a[i] + 1, n);
}
multiset<ll> costs;
costs.insert(answer);
set<pair<int, ll>> segs;
segs.insert({1, answer});
set<int> rem;
rem.insert(0);
rem.insert(n + 1);
for (int i = 1; i <= n; i++) {
ll p;
cin >> p;
answer = *prev(costs.end());
cout << answer << " ";
p ^= answer;
// cerr << "p, answer ---> " << p << " " << answer << "\n";
auto itr = rem.insert(p).first;
auto prv = prev(itr);
auto nxt = next(itr);
int l = *prv + 1;
int r = *nxt - 1;
// cerr << "l, r ---> " << l << " " << r << "\n";
auto seg_itr = segs.upper_bound({l, -1});
auto seg = *seg_itr;
segs.erase(seg_itr);
ll curr = seg.second, currL = 0, currR = 0;
costs.erase(costs.find(curr));
if (p - l < r - p) {
currR = curr;
for (int j = l; j < p; j++) {
currL += Get(l, j - 1, a[j] + 1, n);
currR -= Get(p, r, 1, a[j] - 1);
}
currR -= currL;
currR -= Get(p + 1, r, 1, a[p] - 1);
} else {
currL = curr;
for (int j = p + 1; j <= r; j++) {
currR += Get(p + 1, j - 1, a[j] + 1, n);
currL -= Get(l, p, a[j] + 1, n);
}
currL -= currR;
currL -= Get(l, p - 1, a[p] + 1, n);
}
if (l < p) {
costs.insert(currL);
segs.insert({l, currL});
}
if (p < r) {
costs.insert(currR);
segs.insert({p + 1, currR});
}
// cerr << "curr, currL, currR ---> " << curr << " " << currL << " " << currR << "\n";
// for (auto c : costs) {
// cerr << c << " ";
// }
// cerr << "\n\n";
// if (i == 2) {
// cerr << *costs.rbegin();
// return 0;
// }
}
cout << "\n";
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Dangerous Syscalls
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