1406D - Three Sequences(化简贪心+差分)

最大值只和 m a x ( b n , c 1 ) max(b_n,c_1) max(bn,c1)有关

假设 c 1 = x , 那 么 b 1 = y = a 1 − x c_1=x,那么b_1=y=a_1-x c1=x,b1=y=a1x

如何构造 b 2 , c 2 ? b_2,c_2? b2,c2?

假 设 a 2 > a 1 , 那 么 c 2 必 然 是 越 大 越 好 , 因 为 b 2 + c 2 = a 2 假设a_2>a_1,那么c_2必然是越大越好,因为b_2+c_2=a_2 a2>a1,c2,b2+c2=a2

c 2 大 , b 2 就 会 小 , 且 对 后 续 的 c i 相 对 更 大 , 那 么 后 续 的 b i 也 会 更 小 ) c_2大,b_2就会小,且对后续的c_i相对更大,那么后续的b_i也会更小) c2,b2,ci,bi)

c 2 最 大 能 大 到 c 1 , 满 足 不 递 增 c_2最大能大到c_1,满足不递增 c2c1,

b 2 = a 2 − c 2 b_2=a_2-c_2 b2=a2c2

b 2 = a 2 − c 1 b_2=a_2-c_1 b2=a2c1

b 2 = a 2 − ( a 1 − b 1 ) b_2=a_2-(a_1-b_1) b2=a2(a1b1)

b 2 = b 1 + ( a 2 − a 1 ) b_2=b_1+(a_2-a_1) b2=b1+(a2a1)

惊 人 的 发 现 ! ! 因 为 此 时 a 2 > a 1 , 所 以 b 2 > b 1 , 满 足 递 增 , 且 是 最 优 情 况 ! 惊人的发现!!因为此时a_2>a_1,所以b_2>b_1,满足递增,且是最优情况! !!a2>a1,b2>b1,,!

所 以 有 推 广 , 当 a i > a i − 1 , 最 优 c i = c i − 1 , b i = b i − 1 + ( a i − a i − 1 ) 所以有推广,当a_i>a_{i-1},最优c_i=c_{i-1},b_i=b_{i-1}+(a_i-a_{i-1}) 广,ai>ai1,ci=ci1,bi=bi1+(aiai1)

当 a i < a i − 1 , 最 优 b i = b i − 1 , c i = c i − 1 + ( a i − a i − 1 ) 当a_iai<ai1,bi=bi1,ci=ci1+(aiai1)(这个推法和上面一样)

所 以 我 们 计 算 所 有 ∑ i = 2 n m a x ( 0 , a i − a i − 1 ) = K 所以我们计算所有\sum_{i=2}^{n}max(0,a_i-a_{i-1})=K i=2nmax(0,aiai1)=K

假 定 c 1 = x , 那 么 b 1 = a 1 − x 假定c_1=x,那么b_1=a_1-x c1=x,b1=a1x

那 么 b n = a 1 − x + K 那么b_n=a_1-x+K bn=a1x+K

如 此 一 来 , m a x ( b n , c 1 ) = m a x ( a 1 − x + K , x ) 如此一来,max(b_n,c_1)=max(a_1-x+K,x) ,max(bn,c1)=max(a1x+K,x)

那么容易看出x最优是 a 1 + K 2 \frac{a_1+K}{2} 2a1+K

而 对 于 q 组 询 问 , 只 改 变 了 a l − a l − 1 和 a r + 1 − a r 而对于q组询问,只改变了a_l-a_{l-1}和a_{r+1}-a_r q,alal1ar+1ar

所 以 我 们 直 接 维 护 a 数 组 的 差 分 序 列 a i − a i − 1 所以我们直接维护a数组的差分序列a_i-a_{i-1} aaiai1

每次就可以快速修改差分序列,而且我们也只需要用到差分序列

所 以 可 以 O ( 1 ) 处 理 所以可以O(1)处理 O(1)

#include 
using namespace std;
#define int long long//注意我开了long long 
const int maxn=4e5+10;
int n,a[maxn],K;
void cha_fen(int index,int x)
{
	if( index>n )	return;
	if( a[index]>0 )	K-=a[index];
	a[index]+=x;
	if( a[index]>0 )	K+=a[index];
}
signed main()
{
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		cin >> a[i];
		if( i!=1&&a[i]>a[i-1] )	K+=a[i]-a[i-1];
	}
	for(int i=n;i>=1;i--)	a[i]=a[i]-a[i-1];//只需要a[i]-a[i-1] 
	int a1=a[1];
	cout << ((a1+K+1)>>1) << '\n';//向上取整,本来是除以2,但是有负数取整存在,所以>>1 
	int q; cin >> q;
	while( q-- )
	{
		int l,r,x;
		cin >> l >> r >> x;
		if( l==1 )	a1+=x;
		else cha_fen(l,x);
		cha_fen(r+1,-x);
		cout << ((a1+K+1)>>1) << '\n';
	}
}

你可能感兴趣的:(div题解)