题目链接: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 ",ans); 33 } 34 return 0; 35 }