D. Three Sequences 差分+思维
转自:https://www.cnblogs.com/starve/p/13660672.html
题:http://codeforces.com/contest/1406/problem/D
题意:给定a数组,要求b序列(非降)和c序列(非升)组成a序列(bi+ci=ai),要求输出最小化的最大值max(b1,ci),支持区间加操作
分析:先考虑只求原序列的答案,假设bn=b1+sum(sum>=0,因为是上升序列),由定义:c1=a1-b1;
而经过观察,a序列中差分为正的就由b来处理,差分为负的就由c来处理,所以sum=Σ(差分为正)。
那么答案就是max(bn,c1)化简得max(b1+sum,a1-b1);
只有两种情况:
- b1+sum>=a1-b1,那么b1要满足b1>=(a1-sum)/2,就选前者;
- b1+sum<=a1-b1,那么b1要满足b1<=(a1-sum)/2,就选后者;
然后,因为我们要最小化这个值,那么选择前者时,b1不能大太大,选择后者时b1不能小太小,所以综合b1=(a1-sum)/2。
接着就是区间加,影响的就只有l ,r+1位置的差分值,简单维护一下更新答案。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int M=2e5+5; 5 ll a[M],dis[M]; 6 int main(){ 7 int n; 8 scanf("%d",&n); 9 for(int i=1;i<=n;i++) 10 scanf("%lld",&a[i]); 11 ll sum=0; 12 for(int i=2;i<=n;i++) 13 sum+=max(0ll,a[i]-a[i-1]),dis[i]=a[i]-a[i-1]; 14 ll b1=(a[1]-sum)/2; 15 printf("%lld\n",max(b1+sum,(a[1]+sum)/2)); 16 int m; 17 scanf("%d",&m); 18 for(int l,r,x,i=1;i<=m;i++){ 19 scanf("%d %d %d",&l,&r,&x); 20 if(l==1) 21 a[1]+=1ll*x; 22 else{ 23 ll las=dis[l];///上次差分值 24 sum-=max(0ll,las); 25 sum+=max(0ll,las+x); 26 dis[l]+=x; 27 } 28 /// 29 if(r!=n){ 30 ll las=dis[r+1]; 31 sum-=max(0ll,las); 32 sum+=max(0ll,las-x); 33 dis[r+1]-=x; 34 } 35 b1=(a[1]-sum)/2; 36 printf("%lld\n",max(b1+sum,(a[1]+sum)/2)); 37 } 38 return 0; 39 }