ABC276F

[[Segment Tree]] [[Expectation]]

My Sol.

先是我的做法

把max函数拆掉:\(\max\{x,y\}=\frac{1}{2}*(x+y+|x-y|)\)
然后我们的 \(x\)\(y\) 是在同一个序列 \(A\) 里取的
所以转化一下答案

\(\mathbb{E}(\max\{x,y\})=\bar{A}+\frac{\sum_{i=1}^n\sum_{j=i+1}^n|a_i-a_j|}{n^2}\)

所以可以令 \(A\) 有序,式子化为:
\(\mathbb{E}(\max\{x,y\})=\bar{A}+\sum_{i=1}^n\frac{cnt(1\to a_{i-1})*a_i-sum(1\to a_{i-1})+sum(a_{i+1}\to ma)-cnt(a_{i+1}\to ma)*a_i}{n^2}\)

分母上面的式子可以用数据结构维护,我写了个线段树

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=200005,mod=998244353;
int n;
using ll=long long;
ll pw(ll x,int a=mod-2){
	ll ret=1ll;
	for(;a;a>>=1){
		if(a&1)ret=ret*x%mod;
		x=x*x%mod;
	}
	return ret;
}
struct T{
	ll sum,cnt;
	T operator+(const T&a){
		return T{(sum+a.sum)%mod,cnt+a.cnt};
	}
}_[N<<2];
ll a[N],an,aan,ma;
#define ls (p<<1)
#define rs (p<<1|1)
int x,y;
void add(int l,int r,int p){
	if(l==r){
		_[p]=_[p]+T{l,1};
		return;
	}
	int m=l+r>>1;
	if(x<=m)add(l,m,ls);
	else add(m+1,r,rs);
	_[p]=_[ls]+_[rs];
}
T qry(int l,int r,int p){
	T ret={0ll,0ll};
	if(l>r||l>y||r<x)return ret;
	if(x<=l&&r<=y)return _[p];
	int m=l+r>>1;
	if(x<=m)ret=ret+qry(l,m,ls);
	if(y>m)ret=ret+qry(m+1,r,rs);
	return ret;
}
T s1,s2,s3;
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)scanf("%lld",a+i),ma=max(a[i],ma);ma++;
	for(int i=1;i<=n;i++){
		(aan+=a[i])%=mod;
		x=1,y=a[i]-1;s1=qry(1,ma,1);
		x=a[i]+1,y=ma;s2=qry(1,ma,1);
		x=a[i],y=a[i];s3=qry(1,ma,1);
		(an+=((s1.cnt*a[i]%mod-s1.sum+mod)%mod+(s2.sum-s2.cnt*a[i]%mod+mod)%mod)%mod)%=mod;
		x=a[i];add(1,ma,1);
		printf("%lld\n",(an*pw(i*i%mod)%mod+aan*pw(i)%mod)%mod);
	}
}

我之前的模数会撞segment tree里的p,以后要注意

因为 \(i*i\) 会爆int,调了40min没调出来

我成了一个坚定的#define int long long主义者


Another Sol.

我们不化式子

考虑算出加这个数对上次期望的影响

加一个数,就相当于样本空间里多了 \(i\)

我们只要算出这个多出的贡献和

它只会对值小于 \(a_i\) 的点产生影响,所以就是求一个\(cnt(1\to a_{i-1})*a_i+sum(a_{1+1}\to ma)\)就行了

下面是QY的赛时代码:

# include <bits/stdc++.h>
# define int long long
# define wheneveright signed main
# define pii pair < int, int >
# define mp make_pair
# define x first
# define y second
using namespace std;

const int maxn = 200005;
const int N = 200000;
const int mod = 998244353;

void Add (pii & A, pii B) { A.x += B.x; A.y += B.y; return ; }

int inv (int x, int y = mod - 2) {
	int ret = 1;
	while (y) {
		if (y & 1) ret = ret * x % mod;
		x = x * x % mod; y >>= 1;
	}
	return ret % mod;
}

struct reader {
	template <typename Type>
	reader & operator >> (Type & ret) {
		int f = 1; ret = 0; char ch = getchar ();
		for (;!isdigit (ch); ch = getchar ()) if (ch == '-') f = -f;
		for (; isdigit (ch); ch = getchar ()) ret = (ret * 10) + ch - '0';
		ret *= f; return * this;
	}
} fin;

# define ls(id) ((id) << 1)
# define rs(id) ((id) << 1 | 1)

int val[maxn << 2], sum[maxn << 2];

void push_up (int id) {
	val[id] = val[ls (id)] + val[rs (id)];
	sum[id] = sum[ls (id)] + sum[rs (id)];
	return ;
}

void update (int id, int l, int r, int pos, int k) {
	if (l == pos && pos == r) {
		sum[id] += k * pos;
		val[id] += k;
		return void ();
	}
	int mid = (l + r) >> 1;
	if (pos <= mid) update (ls (id), l, mid, pos, k);
	else update (rs (id), mid + 1, r, pos, k);
	return push_up (id);
}

int find_mid (int id, int l, int r, int rk) {
	if (l == r) return l;
	int mid = (l + r) >> 1;
	if (rk <= val[ls (id)]) return find_mid (ls (id), l, mid, rk);
	return find_mid (rs (id), mid + 1, r, rk - val[ls (id)]);
}

pii query (int id, int l, int r, int L, int R) {
	if (L > R) return mp (0ll, 0ll);
	if (L <= l && r <= R) return mp (val[id], sum[id]);
	int mid = (l + r) >> 1; pii ret = mp (0ll, 0ll);
	if (L <= mid) Add (ret, query (ls (id), l, mid, L, R));
	if (mid < R) Add (ret, query (rs (id), mid + 1, r, L, R));
	return ret;
}

# undef ls
# undef rs

int n, p, now;

wheneveright () {
	freopen("1.in","r",stdin);
	freopen("std.out","w",stdout);
	fin >> n; now = 0;
	for (int i = 1; i <= n; i++) {
		fin >> p;
		now = (now + p) % mod;
		pii L = query (1, 1, N, 1, p);
		pii R = query (1, 1, N, p + 1, N);
		now = (now + p * L.x * 2 % mod) % mod;
		now = (now + R.y * 2 % mod) % mod;
		printf ("%lld\n", (now * inv (i * i % mod)) % mod);
		update (1, 1, N, p, 1);
	}
	return 0;
}

可以看出我的写法大大复杂化了

posted @ 2022-12-11 11:47  -WD-  阅读(59)  评论(0)    收藏  举报