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;
}

猜你喜欢

转载自www.cnblogs.com/Hawking-llfz/p/11595575.html