ABC276F
设 \(b_x\) 表示第 \(x\) 次操作的期望权值,由题意可得:
\[b_x=x^{-2}\times \sum\limits_{1 \leq i,j \leq x}\max(a_i,a_j)
\]
前面的部分可通过求逆元直接获得。设后面那部分为 \(c_x\),递推计算 \(c_x\) 的值,只需要计算新增添的数 \(a_x\) 对 \(c_x\) 的影响。对于 \(a_1\) 到 \(a_{x-1}\) 中所有小于 \(a_x\) 的数 \(a_i\),\(\max(a_i,a_x)=a_x\),否则 \(\max(a_i,a_x)=a_i\),于是开两个树状数组维护 \(a_1\) 到 \(a_{x-1}\) 中小于等于 \(a_x\) 的数的个数 \(\text{cnt}\),以及 \(a_1\) 到 \(a_{x-1}\) 中比 \(a_x\) 大的数的和 \(\text{sum}\)。由于选到相同的两个数调换顺序为两种情况,所以:
\[c_x=c_{x-1}+\text{cnt}\times a_x\times2+\text{sum}\times2+a_x
\]
注意不要少取模,时间复杂度 \(O(n \log n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll SIZE = 200005;
const ll mod = 998244353;
ll n;
ll a[SIZE];
ll cnt[SIZE];
ll sum[SIZE];
inline ll rd(){
ll f = 1, x = 0;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return f*x;
}
ll lowbit(ll x){
return x & (-x);
}
void addc(ll x, ll val){
for(ll i = x; i <= 200000; i += lowbit(i)) cnt[i] += val;
}
void adds(ll x, ll val){
for(ll i = x; i <= 200000; i += lowbit(i)) sum[i] = (sum[i] + val) % mod;
}
int askc(ll x){
ll jl = 0;
for(ll i = x; i; i -= lowbit(i)) jl += cnt[i];
return jl;
}
int asks(ll x){
ll jl = 0;
for(ll i = x; i; i -= lowbit(i)) jl = (jl + sum[i]) % mod;
return jl;
}
ll power(ll x, ll y){
ll jl = 1;
while(y){
if(y&1) jl = (jl * x) % mod;
x = (x * x) % mod;
y >>= 1;
}
return jl;
}
int main(){
n = rd();
for(ll i = 1; i <= n; i++){
a[i] = rd();
}
ll jl = a[1], ss = a[1]; printf("%lld\n", a[1]);
addc(a[1], 1);
adds(a[1], a[1]);
for(ll i = 2; i <= n; i++){
ll x = askc(a[i]);
jl = (jl + ((x * a[i] % mod) * 2ll % mod)) % mod;
x = ((ss - asks(a[i])) % mod + mod) % mod;
jl = (jl + (x * 2ll % mod)) % mod;
jl = (jl + a[i]) % mod;
printf("%lld\n", (jl * power(i*i%mod, mod-2) % mod));
addc(a[i], 1);
adds(a[i], a[i]);
ss = (ss + a[i]) % mod;
}
return 0;
}

浙公网安备 33010602011771号