ABC261F 题解

前言

题目传送门!

更好的阅读体验?

非常好的数据结构优化题。

思路

对于第 \(x\) 次询问,答案为 \(\dfrac{\sum\limits_{i=1}^x\sum\limits_{j=1}^x \max(a_i, a_j)}{x^2}\)。分母显然可以用逆元求,所以看上面那一坨。

看上面这幅图就比较显然了,我们只需要在线维护数据结构,支持:

  • 求出有多少个 \(a_j \le a_i\)
  • 求出所有满足 \(a_j > a_i\)\(\sum a_j\)
  • 加入一个元素 \(a_i\)

注意到 \(\forall a_i \le 2 \times 10^5\),所以直接上权值树状数组即可,一个维护数量,一个维护总和。

代码

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2e5 + 5, mod = 998244353;
int inv(int x, int y = mod - 2)
{
	int ans = 1;
	while (y)
	{
		if (y & 1) ans = 1ll * ans * x % mod;
		x = 1ll * x * x % mod;
		y >>= 1;
	}
	return ans;
}
struct BIT { //权值树状数组 
	int idx[N];
	int lowbit(int x) {return x & -x;}
	void update(int i, int k) {for (; i < N; i += lowbit(i)) (idx[i] += k) %= mod;}
	int query(int i) {int ans = 0; for (; i; i -= lowbit(i)) ans = (ans + idx[i]) % mod; return ans;}
} cnt, sum;
int main()
{
	int n, total = 0, ans = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		int a;
		scanf("%d", &a);
		ans += (2ll * cnt.query(a) + 1) * a % mod;         ans %= mod;
		ans += (2ll *(total - sum.query(a)) % mod + mod) % mod; ans %= mod;
		
		printf("%d\n", 1ll * ans * inv(1ll * i * i % mod) % mod);
		total = (total + a) % mod;
		cnt.update(a, 1), sum.update(a, a);
	}
	return 0;
}

希望能帮助到大家!

posted @ 2023-05-26 19:44  liangbowen  阅读(42)  评论(0编辑  收藏  举报