AT2442 [joi2017]fohen phenomenon 差分

题目链接:https://www.luogu.com.cn/problem/AT2442 或 https://atcoder.jp/contests/joi2017ho/tasks/joi2017ho_a

差分的博客:https://www.luogu.com.cn/blog/RPdreamer/ci-fen-and-shu-shang-ci-fen 

题单:https://www.luogu.com.cn/training/4013 然后P3948就是模板题,就不写了

 

题意:给定n+1个点0...n,s,t。若当前点海拔A[i]>A[i+1],则气温上升(A[i]-A[i+1])*T;否则气温下降(A[i+1]-A[i])*S。q次询问,每次给出l,r,x,表示点l到点r海拔上升x,每次询问后输出最后一个点n的气温。

看到这种形式:(A[i+1]-A[i])*S,考虑差分的思想,记Bi=A[i]-A[i-1]。注意到每次给l--r之间的数加上同一个数x,变化的差值只有B[l]和B[r+1](特别注意当r=n时不考虑B[r+1]),所以先从ans里去掉上一次b[l]和b[r+1]对温度造成的影响,再对差分数组单点操作:b[l]+=x,b[r+1]-=x,最后再加上当前的b[l]点和b[r+1]造成的影响,即得到当前的ans。要开ll,其实我不明白为什么对数组a和b开了ll才过,但我这么改了然后就过了......

这题我一开始想,区间更新,单点查询,肯定是对差分数组求前缀和。但看到每次区间加完都要查询就有点懵逼,因为用差分数组一般是先进行一波区间更新,再进行一波单点查询。仔细想想其实关键点就是区间操作后,只有两处的差分值会变化,而且询问的总是最后一个点的温度,所以每次更新答案即可

 

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 const int maxn=2000+10;
 6 ll a[maxn],b[maxn];
 7 int n,q,s,t,i,j,k;
 8 ll ans;
 9 
10 int main(){
11     memset(a,0,sizeof(a));
12     memset(b,0,sizeof(b));
13     ans=0;
14     //freopen("at2442.txt","r",stdin);
15     scanf("%d%d%d%d",&n,&q,&s,&t);
16     for (i=0;i<=n;i++) scanf("%lld",&a[i]);
17     for (i=1;i<=n;i++) {
18         b[i]=a[i]-a[i-1];
19         if (b[i]>0) ans-=b[i]*s;else ans+=(-b[i]*t);
20     }
21     for (i=1;i<=q;i++){
22         int l,r,x;
23         cin>>l>>r>>x;
24         if (b[l]>0) ans+=b[l]*s;else ans+=b[l]*t;
25         b[l]+=x;
26         if (b[l]>0) ans-=b[l]*s;else ans+=(-b[l]*t);
27         if (r<n){
28             if (b[r+1]>0) ans+=b[r+1]*s;else ans+=b[r+1]*t;
29             b[r+1]-=x;
30             if (b[r+1]>0) ans-=b[r+1]*s;else ans+=(-b[r+1]*t);
31         }
32         printf("%lld\n",ans);
33     }
34     return 0;
35 }
AT2442

 

posted @ 2020-05-30 18:20  coastal_taipan  阅读(177)  评论(0编辑  收藏  举报