Atcoder Regular Contest 126 E - Infinite Operations(权值线段树)

补两个月前鸽掉的题解.jpg

首先不妨假设 \(a\) 从大到小排好序,那么一件显然的事情是操作相邻的两数最优。考虑构造函数 \(f(a)=\sum\limits_{i<j}|a_i-a_j|\),那么容易发现每次对相邻两个 \(a_i,a_{i+1}\) 操作 \(x\) 之后,\(f(a)\) 会恰好减少 \(2x\),而最终 \(a\) 序列所有元素相等,故最终 \(f(a)=0\),答案等于 \(\dfrac{f(a)}{2}\)

求解 \(f(a)\) 可以树状数组,这一部分是容易的,不再赘述。

const int MAXN=3e5;
const int MAXP=MAXN<<6;
const int MAXV=1e9;
const int MOD=998244353;
const int INV2=MOD+1>>1;
struct node{int ch[2],sum,cnt,sumd;}s[MAXP+5];
int n,qu,a[MAXN+5],rt,ncnt;
void pushup(int k){
	s[k].cnt=s[s[k].ch[0]].cnt+s[s[k].ch[1]].cnt;
	s[k].sum=(s[s[k].ch[0]].sum+s[s[k].ch[1]].sum)%MOD;
	s[k].sumd=(0ll+s[s[k].ch[0]].sumd+s[s[k].ch[1]].sumd+
	1ll*s[s[k].ch[1]].sum*s[s[k].ch[0]].cnt%MOD-
	1ll*s[s[k].ch[0]].sum*s[s[k].ch[1]].cnt%MOD+MOD)%MOD;
}
void insert(int &k,int l,int r,int p,int coef){
	if(!k)k=++ncnt;
	if(l==r){
		s[k].sum=(0ll+s[k].sum+coef*p+MOD+MOD)%MOD;
		s[k].cnt+=coef;return;
	}int mid=l+r>>1;
	if(p<=mid)insert(s[k].ch[0],l,mid,p,coef);
	else insert(s[k].ch[1],mid+1,r,p,coef);
	pushup(k);
}
int main(){
#ifdef LOCAL
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
#endif
	scanf("%d%d",&n,&qu);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),insert(rt,1,MAXV,a[i],1);
	while(qu--){
		int x,v;scanf("%d%d",&x,&v);insert(rt,1,MAXV,a[x],-1);
		a[x]=v;insert(rt,1,MAXV,a[x],1);
		printf("%d\n",1ll*INV2*s[rt].sumd%MOD);
	}
	return 0;
}
posted @ 2022-12-20 19:10  tzc_wk  阅读(54)  评论(1)    收藏  举报