[CodeForces935F]Fafa and Array

题意:

给出一个序列 A A ,定义函数f(A)=i=1n1|aiai+1|

给出两种操作:

1.l 1. l r r x ,在区间 [l,r] [ l , r ] 内找一个位置,使得把这个位置的值加上 x x 后,f(A) 最大,求这个最大值

2.l 2. l r r x ,把区间 [l,r] [ l , r ] 加上 x x

n105,q105,xi109


ans=f(A) a n s = f ( A )

考虑 ai+x a i + x ai1,ai+1 a i − 1 , a i + 1 的大小关系

一: ai+x<ai1,ai+x<ai+1 a i + x < a i − 1 , a i + x < a i + 1

Δ=2x Δ = − 2 x

二: ai1<ai+x<ai+1 a i − 1 < a i + x < a i + 1

Δ=(|(ai+x)ai+1|+|ai1(ai+x)|)(|aiai+1|+|ai1ai|) Δ = ( | ( a i + x ) − a i + 1 | + | a i − 1 − ( a i + x ) | ) − ( | a i − a i + 1 | + | a i − 1 − a i | )

=x+|aiai1+x|+|aiai1|0 = − x + | a i − a i − 1 + x | + | a i − a i − 1 | ≤ 0

三: ai1ai+x,ai+1ai+x a i − 1 ≤ a i + x , a i + 1 ≤ a i + x

再考虑 ai a i ai1,ai+1 a i − 1 , a i + 1 的大小关系

①: ai1ai,ai+1ai,Δ=2x a i − 1 ≤ a i , a i + 1 ≤ a i , Δ = 2 ∗ x

②: ai1ai<ai+1,Δ=2x2(ai+1ai) a i − 1 ≤ a i < a i + 1 , Δ = 2 ∗ x − 2 ∗ ( a i + 1 − a i )

③: ai<ai1,ai<ai+1,Δ=2x2[(ai1ai)+(ai+1ai)] a i < a i − 1 , a i < a i + 1 , Δ = 2 ∗ x − 2 ∗ [ ( a i − 1 − a i ) + ( a i + 1 − a i ) ]

显然只有第三种情况是可能对答案贡献是正的

所以我们可以考虑用线段树维护 min{max(0,ai1ai)+max(0,ai+1ai)} m i n { m a x ( 0 , a i − 1 − a i ) + m a x ( 0 , a i + 1 − a i ) }

区间修改,考虑差分,令 ai=ai+1ai a i = a i + 1 − a i

那么我们就是维护 min{max(0,ai1)+max(0,ai)} m i n { m a x ( 0 , − a i − 1 ) + m a x ( 0 , a i ) }

注意特判一下 l=1 l = 1 , r=n r = n 的情况

那么有没有 Δ Δ 一定是负数的情况呢?

有,当 l=r l = r 时,我们只能修改这个值,所以可能出现负贡献,特判一下就好了

#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void sd(T&x){
    char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45)y=-1;x=c-48;
    while(c=gc(),47<c&&c<58)x=x*10+c-48;x*=y;
}
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
template<class T>inline void we(T x){
    if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e5+5;
const long long inf=1e18;
typedef long long ll;
int n,m;ll ans,a[N],tr[N<<2];
#define lc p<<1
#define rc p<<1|1
inline void up(int p){tr[p]=min(tr[lc],tr[rc]);}
void build(int p,int L,int R){
    if(L==R){
        if(L>1)tr[p]=max(0ll,a[L])+max(0ll,-a[L-1]);
        ans+=abs(a[L]);return;
    }int mid=(L+R)>>1;
    build(lc,L,mid),build(rc,mid+1,R);
    up(p);
}
void mdy(int p,int L,int R,int x,int w){
    if(L==R){
        ans+=abs(a[L]+w)-abs(a[L]),a[L]+=w;
        if(x>1)tr[p]=max(0ll,-a[L-1])+max(0ll,a[L]);
        if(w&&x<n-1)mdy(1,1,n-1,x+1,0);return;
    }int mid=(L+R)>>1;
    if(x<=mid)mdy(lc,L,mid,x,w);
    else mdy(rc,mid+1,R,x,w);up(p);
}
ll qry(int p,int L,int R,int a,int b){
    if(a<=L&&R<=b)return tr[p];
    int mid=(L+R)>>1;
    if(b<=mid)return qry(lc,L,mid,a,b);
    if(a>mid)return qry(rc,mid+1,R,a,b);
    return min(qry(lc,L,mid,a,b),qry(rc,mid+1,R,a,b));
}
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    sd(n);int op,l,r,x;
    fp(i,1,n)sd(a[i]);
    fp(i,1,n)a[i]=a[i+1]-a[i];
    build(1,1,n-1);sd(m);
    while(m--){
        sd(op),sd(l),sd(r),sd(x);
        if(op==1){
            if(l==r){
                if(l==1)we(ans-abs(a[l])+abs(a[l]-x));
                else if(l==n)we(ans-abs(a[l-1])+abs(a[l-1]+x));
                else we(ans-abs(a[l-1])-abs(a[l])+abs(a[l-1]+x)+abs(a[l]-x));
            }else{
                ll tp=2*(x-qry(1,1,n-1,l>1?l:2,r));
                if(l==1)cmax(tp,-abs(a[l])+abs(a[l]-x));
                if(r==n)cmax(tp,-abs(a[r-1])+abs(a[r-1]+x));
                we(ans+max(0ll,tp));
            }
        }else{
            l>1?mdy(1,1,n-1,l-1,x):void();
            r<n?mdy(1,1,n-1,r,-x):void();
        }
    }
return Ot(),0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值