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;
}
posted @ 2025-04-27 21:42  quanjun  阅读(40)  评论(0)    收藏  举报