Codeforces Round #670 (Div. 2) D. Three Sequences(思维)

题目链接:https://codeforces.ml/contest/1406/problem/D

题目大意:

  给一个序列ai,有一个非递减序列bi和非递减序列ci,要求每一个位置上的bi和ci的和要等于ai,要求bi和ci中的最大值最小,求这个最大值。同时有修改操作,q次修改,给l到r区间的数字加x, 1 < = n < = 1 0 5 , 1 < = q < = 1 0 5 1<=n<=10^5,1<=q<=10^5 1<=n<=105,1<=q<=105

题目思路:

  好久没训练了,思维真的跟不上了。。好多并不是很难的思维题完全想不到,得加强训练了。这题一看到就以为是线段树,看了好久都没看出有关的性质,挺糟糕的。。其实有个很容易发现的性质,就是每次bi和ci的变化都跟ai的差分有关。在得到差分后可以发现,如果是正差分,那一定是给bi好,因为如果分一点给ci,那么bi只会更大,变得更烂,反之亦然。所以正差分给b,负差分给c。同时由于bi非递减,ci非递增,所以答案是 m a x ( b n , c 1 ) max(b_n,c_1) max(bn,c1),由于 b 1 + c 1 = a 1 b_1+c_1=a_1 b1+c1=a1所以 c 1 = a 1 − b 1 c_1=a_1-b_1 c1=a1b1,刚才又得到结论,只有在正差分才给b,那么假设正差分的和为d, b n = b 1 + d b_n=b_1+d bn=b1+d所以答案就是 m a x ( a 1 − b 1 , b 1 + d ) max(a_1-b_1,b_1+d) max(a1b1,b1+d),很明显是二者相等最小,那么 a 1 − b 1 = b 1 + d a_1-b_1=b_1+d a1b1=b1+d a 1 a_1 a1 d d d是已知的数,可以得到 b 1 = ⌊ a 1 − d 2 ⌋ b_1=\lfloor \frac{a_1-d}{2} \rfloor b1=2a1d,代入原式,发现我们现在只需要维护 a 1 , d a_1,d a1,d,还有个很舒服的事情就是对l r区间加x的话,仅仅只有 a [ l ] − a [ l − 1 ] a[l]-a[l-1] a[l]a[l1] a [ r + 1 ] − a [ r ] a[r+1]-a[r] a[r+1]a[r]这两个差分变化了,所以只用关心这两个地方就行。需要注意的就是l为1和r为n的时候,对应那一端没有差分变化。

以下是代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)

const int MAXN = 1e6+5;
const int MOD = 998244353;
int n,q,l,r,x;
ll a[MAXN],d[MAXN];
int main(){
    
    
    while(~scanf("%d",&n)){
    
    
        rep(i,1,n)scanf("%I64d",&a[i]);
        ll sum=0;
        rep(i,2,n){
    
    
            d[i]=a[i]-a[i-1];
            if(d[i]>0)sum+=d[i];
        }
        ll temp=(a[1]-sum)/2;
        ll ans=max(temp+sum,a[1]-temp);
        printf("%I64d\n",ans);
        scanf("%d",&q);
        while(q--){
    
    
            scanf("%d%d%d",&l,&r,&x);
            if(l==1)a[1]+=x;
            else{
    
    
                if(d[l]>0)sum-=d[l];
                d[l]+=x;
                if(d[l]>0)sum+=d[l];
            }
            if(r<n){
    
    
                if(d[r+1]>0)sum-=d[r+1];
                d[r+1]-=x;
                if(d[r+1]>0)sum+=d[r+1];
            }
            ll temp=(a[1]-sum)/2;
            ll ans=max(temp+sum,a[1]-temp);
            printf("%I64d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/toohandsomeIeaseId/article/details/108856527