Codeforces Round #670 (Div. 2) D. Three Sequences(差分序列、数学思维分析)

D. Three Sequences

D. Three Sequences
题意:给定一个长度为 n n n的序列 a [ ] a[] a[],要求把他分成两个序列 b [ ] , c [ ] b[],c[] b[],c[]

  1. a [ i ] = b [ i ] + c [ i ] a[i]=b[i]+c[i] a[i]=b[i]+c[i]
  2. b [ ] b[] b[]是一个非递减序列
  3. c [ ] c[] c[]是一个非递增序列
  4. m a x ( b i , c i ) max(b_i,c_i) max(bi,ci)尽可能小

之后有 q ( 1 e 5 ) q(1e5) q(1e5)次对于 a [ ] a[] a[]的修改,给定 l , r , x l,r,x l,r,x:对 [ l , r ] [l,r] [l,r]范围内的 a i a_i ai都增加 x x x
要求给出整个序列中的 m a x ( m a x ( b i , c i ) ) max(max(b_i,c_i)) max(max(bi,ci))

思路:看见 q q q次修改,想到差分序列,但是这题在想到用差分时候还是差了一点,手推一下感觉好像还要处理每次之前的最大值,用线段树或者树状数组记录修改。其实不仅仅对于数列 a [ ] a[] a[]需要进行差分,还要对于 b [ ] 、 c [ ] b[]、c[] b[]c[]进行差分分析

  • 由于 b [ ] b[] b[]是一个非递减序列。 c [ ] c[] c[]是一个非递增序列,那么对于 b [ ] b[] b[]的差分数列而言,每个都大于0;对于 c [ ] c[] c[]的每个差分数列而言,每个都小于0。
  • 由递增以及递减关系,可以把题目所求答案的 m a x ( m a x ( b i , c i ) ) max(max(b_i,c_i)) max(max(bi,ci))变成 m a x ( b n , c 1 ) max(b_n,c_1) max(bn,c1)
  • 问题就转换成了把 a [ ] 的 差 分 数 列 d a [ ] a[]的差分数列da[] a[]da[]拆分成一个正数(或0)和一个负数(或0),下面就是需要拆分的策略了。
  • 对于题里面给定的样例推理一下就可以发现:
    • 如果目前的 d a i da_i dai为正数,就直接全给 b i b_i bi,而 c i c_i ci则加上 0 0 0 因为如果变成一个正数 K K K和负数 k k k,那么 K > d a i K>da_i K>dai一定成立,这就会造成 b n b_n bn的增大。
    • 同理,如果目前的 d a i da_i dai为负数,就直接全给 c i c_i ci,而 b i b_i bi则加上 0 0 0 因为如果变成一个正数 K K K和负数 k k k,那么 k < d a i k<da_i k<dai一定成立,这就会造成 c 1 c_1 c1的增大。
  • 经过上述的两个操作我已经能够保证 b [ ] , c [ ] b[],c[] b[],c[]的增减性了。现在就相当于已经知道了初值分别是 b 1 , c 1 ( 在 这 里 我 设 b i 为 x ) b_1,c_1(在这里我设b_i为x) b1,c1(bix)的函数(雾?)。那么现在我只要合理分配初始值,就能使得 m a x ( b n , c 1 ) max(b_n,c_1) max(bn,c1)最小化。因为这里的 c 1 = a 1 − x c_1=a_1-x c1=a1x是一个已知值。我要求的就是 b n = x + ∑ i = 2 n m a x ( 0 , d a i ) b_n=x+\sum_{i=2}^n max(0,da_i) bn=x+i=2nmax(0,dai)
  • 这里把他们均分当然就是最小的时候,即 x + ∑ i = 2 n m a x ( 0 , d a i ) = a 1 − x x+\sum_{i=2}^n max(0,da_i)=a_1-x x+i=2nmax(0,dai)=a1x,在下面的代码中我把 ∑ i = 2 n m a x ( 0 , d a i ) \sum_{i=2}^n max(0,da_i) i=2nmax(0,dai) m a x x maxx maxx表示

接下来留给我的就是对于差分序列的维护,因为其实每次只修改了 a l , a r + 1 a_l,a_{r+1} al,ar+1两个值,所以只要修改前判断是否大于0,减去大于0的,修改后判断是否大于零再加上就好了。
尤其注意1和n的位置!!!这里的差分序列不作数^^(wa4)

LL a[maxn], da[maxn];//差分序列,L-R +1 a[l]+1,a[r+1]-1
LL n, q, xx, ans;
int main()
{
    
    
	cin >> n;
	LL maxx = 0;
	da[1] = 0;
	for (int i = 1; i <= n; i++) {
    
    
		cin >> a[i];
		if (i != 1)da[i] = a[i] - a[i - 1];
		if (da[i] > 0) {
    
    
			maxx += da[i];
		}
	}
	xx = (a[1] - maxx) / 2;
	ans = max(a[1] - xx, xx + maxx);
	cout << ans << endl;
	cin >> q;
	LL l, r, x;
	for (int i = 1; i <= q; i++) {
    
    
		cin >> l >> r >> x;
		if (l != 1 && da[l] > 0)maxx -= da[l];
		if (r != n && da[r + 1] > 0)maxx -= da[r + 1];

		if (l != 1)da[l] += x;
		if (l == 1)a[1] += x;
		if (r != n)da[r + 1] -= x;

		if (l != 1 && da[l] > 0)maxx += da[l];
		if (r != n && da[r + 1] > 0)maxx += da[r + 1];
		xx = (a[1] - maxx) / 2;
		ans = max(a[1] - xx, xx + maxx);
		cout << ans << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44986601/article/details/108674137