AtCoder ABC403G. Odd Position Sum Query 题解 FHQ Treap
题目链接:https://atcoder.jp/contests/abc403/tasks/abc403_g
解题思路:
每个节点额外维护两个信息:
sum[1]
:这个节点所在子树中所有 dfs序为奇数的节点的权值和;sum[0]
:这个节点所在子树中所有 dfs序为偶数的节点的权值和。
使用 FHQ Treap 维护。
然后每次插入一个数字之后的答案即为:根节点的 sum[1]
。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
const long long mod = 1e9;
mt19937 rng(time(0));
struct Node {
int ls, rs, key, pri, sz;
long long sum[2];
Node() {}
Node(int _key) { ls = rs = 0; sum[1] = key = _key; pri = rng(); sz = 1; sum[0] = 0; }
} tr[maxn];
int rt, idx;
void push_up(int u) {
int ls = tr[u].ls, rs = tr[u].rs;
tr[u].sz = tr[ls].sz + tr[rs].sz + 1;
int cc = tr[ls].sz % 2;
if (cc == 0) {
tr[u].sum[0] = tr[ls].sum[0] + tr[rs].sum[1];
tr[u].sum[1] = tr[ls].sum[1] + tr[u].key + tr[rs].sum[0];
}
else { // cc == 1
tr[u].sum[0] = tr[ls].sum[0] + tr[u].key + tr[rs].sum[0];
tr[u].sum[1] = tr[ls].sum[1] + tr[rs].sum[1];
}
}
void split(int u, int x, int &L, int &R) {
if (!u) {
L = R = 0;
return;
}
if (tr[u].key <= x) {
L = u;
split(tr[u].rs, x, tr[u].rs, R);
}
else {
R = u;
split(tr[u].ls, x, L, tr[u].ls);
}
push_up(u);
}
int merge(int L, int R) {
if (!L || !R) return L + R;
if (tr[L].pri > tr[R].pri) {
tr[L].rs = merge(tr[L].rs, R);
push_up(L);
return L;
}
else {
tr[R].ls = merge(L, tr[R].ls);
push_up(R);
return R;
}
}
void ins(int x) {
int L, R;
split(rt, x, L, R);
tr[++idx] = Node(x);
rt = merge(merge(L, idx), R);
}
void del(int x) {
int L, R, p;
split(rt, x, L, R);
split(L, x-1, L, p);
p = merge(tr[p].ls, tr[p].rs);
rt = merge(merge(L, p), R);
}
int q, y, x;
long long z;
int main() {
scanf("%d", &q);
while (q--) {
scanf("%d", &y);
x = (y + z) % mod + 1;
ins(x);
printf("%lld\n", z = tr[rt].sum[1]);
}
return 0;
}