最大值只和 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=a1−x
如何构造 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,满足不递增 c2最大能大到c1,满足不递增
b 2 = a 2 − c 2 b_2=a_2-c_2 b2=a2−c2
b 2 = a 2 − c 1 b_2=a_2-c_1 b2=a2−c1
b 2 = a 2 − ( a 1 − b 1 ) b_2=a_2-(a_1-b_1) b2=a2−(a1−b1)
b 2 = b 1 + ( a 2 − a 1 ) b_2=b_1+(a_2-a_1) b2=b1+(a2−a1)
惊 人 的 发 现 ! ! 因 为 此 时 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>ai−1,最优ci=ci−1,bi=bi−1+(ai−ai−1)
当 a i < a i − 1 , 最 优 b i = b i − 1 , c i = c i − 1 + ( a i − a i − 1 ) 当a_i
所 以 我 们 计 算 所 有 ∑ 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,ai−ai−1)=K
假 定 c 1 = x , 那 么 b 1 = a 1 − x 假定c_1=x,那么b_1=a_1-x 假定c1=x,那么b1=a1−x
那 么 b n = a 1 − x + K 那么b_n=a_1-x+K 那么bn=a1−x+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(a1−x+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组询问,只改变了al−al−1和ar+1−ar
所 以 我 们 直 接 维 护 a 数 组 的 差 分 序 列 a i − a i − 1 所以我们直接维护a数组的差分序列a_i-a_{i-1} 所以我们直接维护a数组的差分序列ai−ai−1
每次就可以快速修改差分序列,而且我们也只需要用到差分序列
所 以 可 以 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';
}
}