CF 1406-D

D. Three Sequences


  • 题意:给一个长度为 n n n 的数组 a a a ,构造两个相同长度的数组 b b b c c c
    要求: b [ i ] + c [ i ] = a [ i ] b[ i ] + c[ i ] = a[ i ] b[i]+c[i]=a[i],并且数组 b b b 单调不减,数组 c c c 单调不增。让我们最小化 m a x ( b [ n ] , c [ 1 ] ) max(b[ n ], c[ 1 ]) max(b[n],c[1]),并且输出。
    除了初始数组,会有 q q q 次区间加操作,对于每次更新完的数组 a a a,同样要输出 m a x ( b [ n ] , c [ 1 ] ) max(b[ n ], c[ 1 ]) max(b[n],c[1])的最小值。

  • 思路: b [ i ] + c [ i ] = a [ i ] b[ i ] + c[ i ] = a[ i ] b[i]+c[i]=a[i] b [ i − 1 ] + c [ i − 1 ] = a [ i − 1 ] b[ i - 1 ] + c[ i - 1 ] = a[ i - 1 ] b[i1]+c[i1]=a[i1] ⇒ \Rightarrow b [ i ] − b [ i − 1 ] + c [ i ] − c [ i − 1 ] = a [ i ] − a [ i − 1 ] b[ i ] - b[ i - 1] + c[ i ] - c[ i - 1] = a[ i ] - a[ i - 1] b[i]b[i1]+c[i]c[i1]=a[i]a[i1]
    因为数组 b b b 单调不减,所以当 a [ i ] − a [ i − 1 ] > = 0 a[ i ] - a[ i - 1] >= 0 a[i]a[i1]>=0 时,令 c [ i ] = c [ i − 1 ] c[ i ] = c[ i - 1] c[i]=c[i1] b [ i ] = b [ i − 1 ] + a [ i ] − a [ i − 1 ] b[ i ] = b[ i - 1] + a[ i ] - a[ i - 1] b[i]=b[i1]+a[i]a[i1]
    因为数组 c c c 单调不增,所以当 a [ i ] − a [ i − 1 ] < 0 a[ i ] - a[ i - 1] < 0 a[i]a[i1]<0 时,令 b [ i ] = b [ i − 1 ] b[ i ] = b[ i - 1] b[i]=b[i1] c [ i ] = c [ i − 1 ] + a [ i ] − a [ i − 1 ] c[ i ] = c[ i - 1] + a[ i ] - a[ i - 1] c[i]=c[i1]+a[i]a[i1]

所以假设 c [ 1 ] = x c[ 1 ] = x c[1]=x,那么 b [ 1 ] = a [ 1 ] − x b[ 1 ] = a[ 1 ] - x b[1]=a[1]x
k = ∑ i = 2 n m a x ( 0 , a [ i ] − a [ i − 1 ] ) k = \displaystyle \sum^{n}_{i = 2}{max(0, a[ i ] - a[i - 1])} k=i=2nmax(0,a[i]a[i1])
由上述的构造我们可以得到 b [ n ] = b [ 1 ] + k = a [ 1 ] − x + k b[ n ] = b[ 1 ] + k = a[ 1 ] - x + k b[n]=b[1]+k=a[1]x+k
所以我们要最小化 m a x ( b [ n ] , c [ 1 ] ) max(b[ n ], c[ 1 ]) max(b[n],c[1]) 也即最小化 m a x ( a [ 1 ] − x + k , x ) max(a[ 1 ] - x + k, x) max(a[1]x+k,x)
显然,当 a [ 1 ] − x + k = = x a[ 1 ] - x + k == x a[1]x+k==x 时,即 x = a [ 1 ] + k 2 x = \displaystyle\frac{a[ 1 ] + k}{2} x=2a[1]+k 时,最大值最小。

关于区间加的操作,这里因为只关心 k k k 值的变化和 a [ 1 ] a[ 1 ] a[1] 值的变化,所以开一个数组 d i f [ i ] = a [ i ] − a [ i − 1 ] dif[ i ] = a[ i ] - a[ i - 1] dif[i]=a[i]a[i1], 我们利用差分的思想,区间 [ l , r ] [l, r] [l,r] 操作只更新差值 d i f [ l ] dif[ l ] dif[l] d i f [ r + 1 ] dif[r + 1] dif[r+1]即可。
但是需要注意的是 d i f [ 1 ] dif[1] dif[1] 影响 a [ 1 ] a[1] a[1] 的更新,而 d i f [ 1 ] dif[1] dif[1] d i f [ n + 1 ] dif[n + 1] dif[n+1] 都不影响 k k k 的更新。

然后 O ( n + q ) O(n + q) O(n+q) 即可解决。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
using namespace std;
typedef long long ll;
const int maxN = 100005;
ll read() {
    
    
    ll x = 0, f = 1; char ch = getchar();
    while(ch < '0' || ch > '9') {
    
     if(ch == '-') f = -f; ch = getchar(); }
    while(ch >= '0' && ch <= '9') {
    
     x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
ll n, a[maxN]; //n->数组长度[1, n]
ll dif[maxN], k;
void solve(){
    
    
    a[1] += dif[1], dif[1] = 0;
    ll c1 = (a[1] + k) >> 1;
    ll bn = a[1] - c1 + k;
    cout << max(c1, bn) << endl;
}
void update(int pos, ll &x, ll val) {
    
    
    if(pos > n) return;
    if(x > 0) {
    
    
        k -= x;
    }
    x += val;
    if(pos <= 1) return;
    if(x > 0) {
    
    
        k += x;
    }
}
int main()
{
    
    
    n = read();
    for(int i = 1; i <= n; ++ i ) {
    
    
        a[i] = read();
        dif[i] = a[i] - a[i - 1];
    }
    dif[1] = 0;
    k = 0;
    for(int i = 2; i <= n; ++ i ) {
    
    
        k += dif[i] > 0 ? dif[i] : 0;
    }
    solve();
    ll q; q = read();
    while(q -- ) {
    
    
        int l, r; ll val;
        cin >> l >> r;
        val = read();
        update(l, dif[l], val);
        update(r + 1, dif[r + 1], -val);
        solve();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/108630816