Loading

ARC126E 做题记录

link

只需要手玩 + 大力猜就能做的题。

我们可以猜测:选择两个数操作,一定把他们变成两者的平均数。这个结论的可信度非常大。

\(g(a_1,a_2,...,a_n)\) 表示 \(a_{1...n}\) 的答案。

我们不妨先尝试点简单的,对于两个数 \(x,y\),钦定 \(x\le y\),显然有 \(g(x,y)=\dfrac {y-x}2\)

对于三个数 \(x,x,y(x\le y)\),我们选择任意一个 \(x\)\(y\) 操作一遍,变为 \(x,\dfrac {x+y}2,\dfrac{x+y}2\),则 \(g(x,x,y)=\frac {y-x}2 +g(x,\frac {x+y}2,\frac {x+y}2)\)。操作有对称性,所以 \(g(x,\frac {x+y}2,\frac {x+y}2)=g(\frac {x+y}2,\frac{x+y}2,y)=g(\frac{x+y}2,y,y)\)

\(h_0(d)=g(x,x+d,x+d)\),则 \(h_0(d)=\frac 12 d+h_0(\frac d2)\),极限取到 \(h_0(d)=d\)

对于三个数 \(x,y,z(x\le y\le z)\),我们有三种方法:

  • 先操作 \(x,z\),变为 \(g(\frac{x+z}2, \frac{x+z}2,y)\)

  • 先操作 \(x,y\),变为 \(g(\frac{x+y}2, \frac{x+y}2,z)\)

  • 先操作 \(y,z\),变为 \(g(\frac{y+z}2, \frac{y+z}2,x)\)

我们计算一下,三种的得分分别是 \(\frac{z-x}2+|\frac{x+z}2-y|,\space z-x,\space z-x\),容易发现前者一定不优于后两者,猜测存在一种最优策略,每次只操作相邻的数字。

后面两种方法的得分相同,猜测相邻数字的操作顺序对答案没有影响。

对于 \(x,x,y,y(x\le y)\),根据上面猜的结论,我们先操作一对 \((x,y)\),得到两个 \(\frac{x+y}2\)。然后再把操作后得到的两个数分别与另外两个数操作,那么 \(g(x,x,y,y)=y-x+g(x+\frac{x+y}4,x+\frac{x+y}4,y-\frac{x+y}4,y-\frac{x+y}4)\)

\(h_1(d)=g(x,x,x+d,x+d)\),则 \(h_1(d)=d+h_1(\frac d2)\),极限取到 \(h_1(d)=2d\)

对于 \(x,y,y,y(x\le y)\),我们操作一对 \((x,y)\),得到 \(g(x,y,y,y)=\frac {y-x}2+g(\frac{x+y}2,\frac{x+y}2,y,y)=\frac {3(y-x)}2\)

我们猜测:有 \(n\)\(x\)\(m\)\(y\),且 \(x\le y\),答案为 \(nm\cdot\frac{y-x}2\)

维护一棵动态开点线段树,每次左右儿子合并时,视为左右边所有数都变成了各自的平均数,然后根据上面的结论计算即可,时间复杂度 \(O(n\log V)\)

  • 启示:

遇到没有切入点的题目,考虑手玩一下简单的情况,不要畏难,一定可以的!

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define pir pair<ll,ll>
#define mkp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
const ll maxn=3e5+10, mod=998244353, M=1e9;
ll n,m,sum[maxn*60],res[maxn*60],inv[maxn],tot,lc[maxn*60],rc[maxn*60],cnt[maxn*60],a[maxn],rt;
void modify(ll &p,ll l,ll r,ll x,ll v){
	if(!p) p=++tot;
	if(l==r){
		cnt[p]+=v;
		sum[p]+=x*v; sum[p]%=mod;
		return;
	} ll mid=l+r>>1;
	if(x<=mid) modify(lc[p],l,mid,x,v);
	else modify(rc[p],mid+1,r,x,v);
	sum[p]=(sum[lc[p]]+sum[rc[p]])%mod, cnt[p]=cnt[lc[p]]+cnt[rc[p]];
	res[p]=(res[lc[p]]+res[rc[p]]+cnt[rc[p]]%mod*cnt[lc[p]]%mod*(sum[rc[p]]*
	inv[cnt[rc[p]]]%mod-sum[lc[p]]*inv[cnt[lc[p]]]%mod))%mod;
}
int main(){
	scanf("%lld%lld",&n,&m);
	inv[1]=1;
	for(ll i=2;i<=n;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	for(ll i=1,x;i<=n;i++){
		scanf("%lld",&x); modify(rt,1,M,x,1); a[i]=x;
	}
	while(m--){
		ll x,y; scanf("%lld%lld",&x,&y);
		modify(rt,1,M,a[x],-1);
		modify(rt,1,M,y,1); a[x]=y;
		printf("%lld\n",(res[rt]+mod)*inv[2]%mod);
	}
	return 0;
}
posted @ 2024-04-03 09:20  Lgx_Q  阅读(8)  评论(0编辑  收藏  举报