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 }

 

posted @ 2020-09-22 20:15  古比  阅读(134)  评论(0编辑  收藏  举报