• AT2442


    差分 + 纯特判过题。

    看了一下大概没人像我这么 zz 吧。

    Description

    给定一个序列 (a_{1dots n }),每次取一段区间对其中所有的数加减一个同样的值,然后按题目所给的条件进行计算。

    修改若干次,前面的修改对于后面的计算会造成影响,求出每一次修改后的答案。

    Solution

    看到区间修改,发现 (l_i,r_ile nle 200,000),暴力修改不可行。可以考虑差分。

    差分后,发现 (qle 200,000),无法进行 (Theta(nq)) 的操作。其中 (q) 次循环是不能省的,所以考虑换个方法统计区间的答案。

    结合题目的条件,每个对答案的贡献都是基于 (a_i)(a_{i+1}) 的差值大小。而 (a_{i+1}-a_i) 又是我们已经处理完的差分数组中的元素。

    假设差分后的数组为 (c),则初始序列的答案为

    [sum_{i=1}^{n} [-c_i imes T(c_i<0)]-sum_{i=1}^n [c_i imes S(c_i>0)] ]

    而对于每一次操作 ((l,r,k)),可以发现,修改之后对答案有影响的位置只有 (l)(r) 两个位置,而其他的值还是不变的。

    所以对于每次操作 ((l,r,k)),我们只需要在上一次的答案基础上修改 (l,r) 两个位置的贡献即可。

    修改 (l,r) 处的贡献,就是比较修改前后 (c_{l},c_{r})(0) 的大小关系,然后按题目所给规则计算即可。具体修改方式不好阐述,但是比较简单,见代码即可。

    时间复杂度 (Theta(n))

    Code

    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define rr register 
    #define maxn 20000010
    #define INF 0x3f3f3f3f
    #define LL long long
    #define Mod 19260817
    #define int long long
    using namespace std;
    
    int n,q,s,t,now,ans1,ans2;
    int a[maxn],c[maxn];
    
    inline int read(){
        rr int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
        return s*w;
    }
    
    signed main(){
        n=read();q=read();
        s=read();t=read();a[0]=read();
        for(int i=1;i<=n;i++){
            c[i]=((a[i]=read())-a[i-1]);
            if(c[i]>0)ans1+=c[i];if(c[i]<0)ans2+=c[i];
        }
        ans1*=-s;ans2*=-t;
        //ans1 统计升温,ans2 统计降温,则答案为 ans1 + ans2; 
        for(int i=1,fr,to,val;i<=q;i++){
            fr=read();to=read();val=read();
            c[fr]+=val;c[to+1]-=val;//差分,则差分前的两个数分别是 c[fr] - val 和 c[to + 1] + val; 
            if(c[fr]-val==0){
                if(c[fr]>0) ans1-=val*s;
                if(c[fr]<0) ans2-=val*t;
            }
            if(c[fr]-val>0){
                if(c[fr]>=0) ans1-=val*s;
                else if(c[fr]<0){
                    ans1+=(c[fr]-val)*s;
                    ans2-=c[fr]*t;
                }
            }
            if(c[fr]-val<0){
                if(c[fr]<=0) ans2-=val*t;
                else if(c[fr]>0){
                    ans2+=(c[fr]-val)*t;
                    ans1-=c[fr]*s;
                }
            }
            
            if(to+1<=n){//差分减的时候可能会超出 n 的范围,此时不用计算它的贡献; 
            //下面的判断和上面是一样的 
                if(c[to+1]+val==0){
                    if(c[to+1]>0) ans1+=val*s;
                    if(c[to+1]<0) ans2+=val*t;
                }
                
                if(c[to+1]+val>0){
                    if(c[to+1]>=0) ans1+=val*s;
                    else if(c[to+1]<0){
                        ans1+=(c[to+1]+val)*s;
                        ans2-=c[to+1]*t;
                    }
                }
                if(c[to+1]+val<0){
                    if(c[to+1]<=0) ans2+=val*t;
                    else if(c[to+1]>0){
                        ans2+=(c[to+1]+val)*t;
                        ans1-=c[to+1]*s;
                    }
                }
            }
            printf("%lld
    ",ans2+ans1);
        }
        return 0;
    }
    
  • 相关阅读:
    Java并发初识
    go交叉编译
    MRC与ARC混合开发配置
    Hibernate配置文件
    LEFT JOIN重复数据
    Ext.ViewPort布局
    Hibernate学习映射文件
    AjaxMethod方法
    DataBinder
    subsonic 获取记录数量
  • 原文地址:https://www.cnblogs.com/KnightL/p/14829247.html
Copyright © 2020-2023  润新知