Live2D

Solution -「ARC 126E」Infinite Operations

Description

  Link.

  给定序列 {an},定义一次操作为:

  • 选择 ai<aj,以及一个 xR+,使得 ai+xajx
  • aiai+x,ajajx,本次操作的得分为 x

  定义序列的得分为进行任意次操作能得到的最大得分和,现给定 m 次形如 axy 的修改操作,在每次修改操作后求出当前序列的得分。

Solution

  定义序列的势能 Φ=i<j|aiaj|,设进行一次操作后得到新势能 Φ,显然有 ΦΦ2x,其中 x 即操作时所选取的正数。同时,取等条件容易看出为 ak,ak(ai,aj),由此,又能得到只要 Φ>0,我们必然能以势能减少 2x 的代价增加 x 分。所以答案就是 Φ2

  选用平衡树来动态维护 Φ 即可支持修改。复杂度 O((n+m)logn)

Code

/*~Rainybunny~*/

#include <bits/stdc++.h>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )

typedef long long LL;

const int MAXN = 6e5, MOD = 998244353, INV2 = 499122177;
int n, m, root, a[MAXN + 5];

inline int mul( const int u, const int v ) { return 1ll * u * v % MOD; }
inline int sub( int u, const int v ) { return ( u -= v ) < 0 ? u + MOD : u; }
inline int add( int u, const int v ) { return ( u += v ) < MOD ? u : u - MOD; }

struct Treap {
	int node, root, ch[MAXN + 5][2], aux[MAXN + 5], val[MAXN + 5];
	int siz[MAXN + 5], sum[MAXN + 5];
	Treap() { srand( 20120712 ); }
	
	inline int newnd( const int v ) {
		++node, aux[node] = rand(), sum[node] = val[node] = v, siz[node] = 1;
		return node;
	}
	
	inline void pushup( const int u ) {
		siz[u] = siz[ch[u][0]] + siz[ch[u][1]] + 1;
		sum[u] = add( add( sum[ch[u][0]], sum[ch[u][1]] ), val[u] );
	}
	
	inline int merge( const int u, const int v ) {
		if ( !u || !v ) return u | v;
		if ( aux[u] < aux[v] ) {
			return ch[u][1] = merge( ch[u][1], v ), pushup( u ), u;
		} else {
			return ch[v][0] = merge( u, ch[v][0] ), pushup( v ), v;
		}
	}
	
	inline void vsplit( const int u, const int k, int& x, int& y ) {
		if ( !u ) return void( x = y = u );
		if ( val[u] <= k ) vsplit( ch[u][1], k, ch[x = u][1], y ), pushup( x );
		else vsplit( ch[u][0], k, x, ch[y = u][0] ), pushup( y );
	}
	
	inline int erase( const int v ) {
		int x, y, z; vsplit( root, v, x, z );
		int ret = add( sub( mul( sub( siz[x], siz[z] ), v ), sum[x] ), sum[z]);
		vsplit( x, v - 1, x, y ), y = merge( ch[y][0], ch[y][1] );
		return root = merge( x, merge( y, z ) ), ret;
	}
	
	inline int insert( const int v ) {
		int x, y = newnd( v ), z; vsplit( root, v, x, z );
		int ret = add( sub( mul( sub( siz[x], siz[z] ), v ), sum[x] ), sum[z]);
		return root = merge( x, merge( y, z ) ), ret;
	}
} trp;

int main() {
	scanf( "%d %d", &n, &m );
	int ans = 0;
	rep ( i, 1, n ) scanf( "%d", &a[i] ), ans = add( ans, trp.insert( a[i] ) );
	for ( int x, v; m--; ) {
		scanf( "%d %d", &x, &v );
		ans = sub( ans, trp.erase( a[x] ) );
		ans = add( ans, trp.insert( a[x] = v ) );
		printf( "%d\n", mul( ans, INV2 ) );
	}
	return 0;
}

posted @   Rainybunny  阅读(73)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示