Luogu P3655 不成熟的梦想家 (未熟DREAMER)
Luogu P3655 不成熟的梦想家 (未熟DREAMER)
解析
- 记录差分数组,每次修改差分值即可
- 对被修改的位置先减去它之前的贡献,然后修改它的值,然后加上它之后的贡献
Code
法一(树状数组 $ \Theta (nlogn) $ )
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int N=2e5+5;
int n,q;
LL s,t,b,now,last,ctr[N];
int lowbit(int u)
{
return u&(-u);
}
void update(int u,LL v)
{
for(;u<=n;u+=lowbit(u)) ctr[u]+=v;
return;
}
LL query(int u)
{
LL res=0;
for(;u;u-=lowbit(u)) res+=ctr[u];
return res;
}
int main()
{
scanf("%d%d%lld%lld%lld",&n,&q,&s,&t,&now);
for(int i=1;i<=n;i++)
{
scanf("%lld",&now);
if(now>last) b-=s*(now-last);
if(now<last) b+=t*(last-now);
update(i,now-last);
last=now;
}
while(q--)
{
int x,y;
LL z;
scanf("%d%d%lld",&x,&y,&z);
LL l1=query(x-1),l2=query(x);
if(l2>l1) b+=s*(l2-l1);
if(l2<l1) b-=t*(l1-l2);
update(x,z);
l1=query(x-1),l2=query(x);
if(l2>l1) b-=s*(l2-l1);
if(l2<l1) b+=t*(l1-l2);
if(y==n)
{
printf("%lld\n",b);
continue;
}
LL r1=query(y),r2=query(y+1);
if(r2>r1) b+=s*(r2-r1);
if(r2<r1) b-=t*(r1-r2);
update(y+1,-z);
r1=query(y),r2=query(y+1);
if(r2>r1) b-=s*(r2-r1);
if(r2<r1) b+=t*(r1-r2);
printf("%lld\n",b);
}
return 0;
}
法二(差分 $ \Theta (n) $ )
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int N=2e5+5;
int n,q;
LL s,t,b,a[N],c[N];
int main()
{
scanf("%d%d%lld%lld%lld",&n,&q,&s,&t,&a[0]);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
c[i]=a[i]-a[i-1];
if(c[i]>0) b-=s*c[i];
if(c[i]<0) b+=t*(-c[i]);
}
while(q--)
{
int x,y;
LL z;
scanf("%d%d%lld",&x,&y,&z);
if(c[x]>0) b+=s*c[x];
if(c[x]<0) b-=t*(-c[x]);
c[x]+=z;
if(c[x]>0) b-=s*c[x];
if(c[x]<0) b+=t*(-c[x]);
if(y==n)
{
printf("%lld\n",b);
continue;
}
if(c[y+1]>0) b+=s*c[y+1];
if(c[y+1]<0) b-=t*(-c[y+1]);
c[y+1]-=z;
if(c[y+1]>0) b-=s*c[y+1];
if(c[y+1]<0) b+=t*(-c[y+1]);
printf("%lld\n",b);
}
return 0;
}
Classical is something not fade,but grow more precious with time pass by,so is dream.梦想这东西和经典一样,永远不会因为时间而褪色,反而更显珍贵。