A Simple Problem with Integers Lazy标记版线段树(区间修改)

 链接:https://ac.nowcoder.com/acm/problem/50454
来源:牛客网

题目描述

给定数列a[1],a[2],…,a[n]a[1],a[2], \dots,a[n]a[1],a[2],,a[n],你需要依次进行q个操作,操作有两类:
1 l r x:给定l,r,x,对于所有i∈[l,r]i \in[l,r]i[l,r],将a[i]加上x(换言之,将a[l],a[l+1],…,a[r]a[l],a[l+1], \dots,a[r]a[l],a[l+1],,a[r]分别加上x);
2 l r:给定l,r,求∑i=lra[i]\sum_{i=l}^ra[i]i=lra[i]的值(换言之,求a[l]+a[l+1]+⋯+a[r]a[l]+a[l+1]+ \dots+a[r]a[l]+a[l+1]++a[r]的值)。

输入描述:

第一行包含2个正整数n,q,表示数列长度和询问个数。保证1≤n,q≤1061 \le n,q \le10^61n,q106。
第二行n个整数a[1],a[2],…,a[n]a[1],a[2], \dots,a[n]a[1],a[2],,a[n],表示初始数列。保证∣a[i]∣≤106|a[i]| \le10^6a[i]106。
接下来q行,每行一个操作,为以下两种之一:
1 l r x:对于所有i∈[l,r]i \in[l,r]i[l,r],将a[i]加上x;
2 l r:输出∑i=lra[i]\sum_{i=l}^ra[i]i=lra[i]的值。保证1≤l≤r≤n,1 \le l \le r \le n,1lrn,∣x∣≤106|x| \le10^6x106。

输出描述:

对于每个2lr操作,输出一行,每行有一个整数,表示所求的结果。
示例1

输入

复制
5 10
2 6 6 1 1
2 1 4
1 2 5 10
2 1 3
2 2 3
1 2 2 8
1 2 3 7
1 4 4 10
2 1 2
1 4 5 6
2 3 4

输出

复制
15
34
32
33
50

备注:

对于所有数据,1≤n,q≤106,1 \le n,q \le10^6,1n,q106,∣a[i]∣≤106|a[i]| \le10^6a[i]106,1≤l≤r≤n,1 \le l \le r \le n,1lrn,∣x∣≤106|x| \le10^6x106。

分析

线段树带lazy标记,就像账单,如果没有必要,一堆人一起加分,要看某个人的分数的时候,再把这个一堆人的加分细分给各个人。

//-------------------------代码----------------------------

#define int ll
const int N = 1e6+10;
int n,m,q;
int a[N];
struct node {
    int l,r,sum,lazy;
}tr[N * 4];

void build(int p,int l,int r) {
    if(l == r) {
        tr[p] = {l,l,a[l],0};
        rt;
    }
    int mid = l + r >> 1;
    build(p << 1,l,mid);
    build(p<<1|1,mid + 1,r);
    tr[p] = {l,r,tr[p<<1].sum + tr[p<<1|1].sum,0};
}

void push_down(int p,int tot) {
    tr[p<<1|1].lazy += tr[p].lazy;
    tr[p<<1].lazy += tr[p].lazy;
    tr[p<<1].sum += (tot - tot / 2) * tr[p].lazy;
    tr[p<<1|1].sum += (tot / 2) * tr[p].lazy;
    tr[p].lazy = 0;
}

void add(int p,int l,int r,int x) {
    if(l <= tr[p].l && tr[p].r <= r) {
        tr[p].lazy += x;
        tr[p].sum += x * (tr[p].r - tr[p].l + 1) ;
        rt;
    }
    if(tr[p].lazy) {
        push_down(p,tr[p].r-tr[p].l+1);
    }
    int mid = tr[p].l + tr[p].r >> 1; 
    if(l <= mid) add(p << 1,l,r,x);
    if(r > mid) add(p << 1 | 1,l,r,x);
    tr[p].sum = tr[p << 1].sum + tr[p<<1|1].sum;
}

// ll query(int p, int l, int r, int nl, int nr){
//             add(1, 1, n, l, r, x);
int query(int p,int l,int r) {
    if(l <= tr[p].l && tr[p].r <= r) {
        return tr[p].sum;
    }
    if(tr[p].lazy) {
        push_down(p,tr[p].r - tr[p].l + 1);
    }
    int mid = tr[p].l + tr[p].r >>1;
    int sum = 0;
    if( l <= mid) sum += query(p << 1, l,r);
    if(r > mid) sum += query(p<<1|1, l ,r) ;
    return sum;
}

void solve()
{
//    cin>>n>>m;
    cin>>n>>q;
    fo(i,1,n) cin>>a[i];
    build(1,1,n);
    fo(i,1,q) {
        int op;cin>>op;
        if(op == 1) {
            int l,r,x;cin>>l>>r>>x;
            add(1,l,r,x);
        } else {
            int l,r;cin>>l>>r;
            cout<<query(1,l,r)<<endl;
//             bd;gg;
        }
    }
//     fo(i,1,2*n) {
//         cout<<tr[i].sum<<' ';
//     }cout<<endl;
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

posted @ 2022-08-07 20:02  er007  阅读(27)  评论(0)    收藏  举报