求助!悬赏3个解决方案

【模板】线段树 1

题目描述

如题,已知一个数列 \{a_i\},你需要进行下面两种操作:

  1. 将某区间每一个数加上 k
  2. 求出某区间每一个数的和。

输入格式

第一行包含两个整数 n, m,分别表示该数列数字的个数和操作的总个数。

第二行包含 n 个用空格分隔的整数 a_i,其中第 i 个数字表示数列第 i 项的初始值。

接下来 m 行每行包含 34 个整数,表示一个操作,具体如下:

  1. 1 x y k:将区间 [x, y] 内每个数加上 k
  2. 2 x y:输出区间 [x, y] 内每个数的和。

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

输入输出样例 #1

输入 #1

5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4

输出 #1

11
8
20

说明/提示

对于 15\% 的数据:n \le 8m \le 10
对于 35\% 的数据:n \le {10}^3m \le {10}^4
对于 100\% 的数据:1 \le n, m \le {10}^5a_i,k 为正数,且任意时刻数列的和不超过 2\times 10^{18}

【样例解释】

样例不对,输出

11
8
16
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int MAX_N=1e6+10;
const int MX=100;
const ll BASE=131;
const ll MOD=10000000007;
const int mxN=84;
const int mxK=14;
const int MAXSIZE=300;
ll n,m,z[MAX_N];
typedef struct ST{
    ll sum[MAX_N],ans[MAX_N];
    inline ll lch(int x){return x<<1;}
    inline ll rsh(int x){return x<<1|1;}
    inline void pushup(ll x){ans[x]=ans[lch(x)]+ans[rsh(x)];return;}
    inline void solve(ll a,ll b,ll c,ll d){
        sum[a]=sum[a]+d;
        ans[a]=ans[a]+d*(b-c+1);
        return;
    }
    inline void pushdown(ll a,ll l,ll r){
        ll mid=(l+r)>>1;
        solve(lch(a),l,mid,sum[a]);
        solve(rsh(a),mid+1,r,sum[a]);
        sum[a]=0;
        return;
    }
    inline void biuding(ll a,ll l,ll r,ll *v){
        sum[a]=0;
        if(l==r){ans[a]=v[l];}
        else{
            ll mid=(l+r)>>1;
            biuding(lch(a),l,mid,v);
            biuding(rsh(a),mid+1,r,v);
            pushup(a);
        }
        return;
    }
    inline void toUP(ll tl,ll tr,ll l,ll r,ll a,ll b){
        if(tl<=l&&r<=tr){ans[a]+=b*(r-l+1);sum[a]+=b;return;}
        pushdown(a,l,r);
        ll mid=(l+r)>>1;
        if(tl<=mid)toUP(tl,tr,l,mid,lch(a),b);
        if(tr>mid)toUP(tl,tr,mid+1,r,rsh(a),b);
        pushup(a);
        return;
    }
    inline ll range(ll tl,ll tr,ll l,ll r,ll a){
        ll cnt=0;
        if(tl<=l&&r<=tr)return ans[a];
        ll mid=(l+r)>>1;
        pushdown(a,l,r);
        if(tl<=mid)cnt+=range(tl,tr,l,mid,lch(a));
        if(tr>mid)cnt+=range(tl,tr,mid+1,r,rsh(a));
        return cnt;
    } 
}ST;
ST tr;
int main(){
    cin>>n>>m;
    ll a,b,c,d;
    for(ll i=1;i<=n;i++)cin>>z[i];
    tr.biuding(1,1,n,z);
    for(ll i=0;i<m;i++){
        cin>>a;
        if(a==1){
            cin>>b>>c>>d;
            tr.toUP(b,c,1,n,1,d);
            continue;
        }
        cin>>b>>c;
        ll ans=tr.range(b,c,1,n,1);
        printf("%lld\n",ans);
    }
    return 0;
}
1 个赞

反了吧

@向耕立 @向耕立 可以了,把b-c+1改成c-b+1就行了

说话算数

1 个赞

(帖子已被作者删除)

1 个赞

。谁让你们能随便开条件的啊,多给赞就算了,解决方案不允许

2 个赞