分块,全WA

P3372 【模板】线段树 1

coritom @ 2024-03-14 18:49:13

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6 + 5; 
int n, m, l[maxn], r[maxn], sum[maxn];
int ans[maxn], a[maxn], pre[maxn], cnt;
void init(){
    int block = sqrt(n);
    int t = n / block;
    if(n % block) t++;
    for(int i = 1; i <= t; i++){
        l[i] = (i - 1) * block + 1;
        r[i] = i * block;
    }
    r[t] = n;
    for(int i = 1; i <= t; i++){
        for(int j = l[i]; j <= r[i]; j++){
            sum[i] += a[j];
        }
    }
    for(int i = 1; i <= n; i++){
        pre[i] = (i - 1) / block + 1;
    }
}
void add(int lt, int rt, int k){
    int p = pre[lt], q = pre[rt];
    if(p == q){
        for(int i = lt; i <= rt; i++) a[i] += k;
        sum[p] += (rt - lt + 1) * k;
    }
    else{
        for(int i = p + 1; i < q; i++) ans[i] += k;
        for(int i = lt; i <= r[p]; i++) a[i] += k;
        sum[p] += (r[p] - lt + 1) * k;
        for(int i = l[q]; i <= rt; i++) a[i] += k;
        sum[q] += (rt - l[q] + 1) * k;
    }
}
int query(int lt, int rt){
    int p = pre[lt], q = pre[rt];
    cnt = 0;
    if(p == q){
        for(int i = lt; i <= rt; i++) cnt += a[i];
        cnt += ans[p] * (rt - lt + 1);
    }
    else{
        for(int i = p + 1; i < q; i++) cnt += sum[i] + ans[i] * (r[i] - l[i] + 1);
        for(int i = lt; i <= r[p]; i++) cnt += a[i];
        cnt += ans[p] * (r[p] - lt + 1) * ans[p];
        for(int i = l[q]; i <= rt; i++) cnt += a[i];
        cnt += (rt - l[q] + 1) * ans[q];
    }
    return cnt;
}
signed main(){
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    init();
    int op, x, y, k;
    while(m--){
        cin >> op >> x >> y;
        if(op == 1){
            cin >> k;
            add(x, y, k);
        }
        else{
            cout << query(x, y) << "\n";
        }
    }
    return 0;
}

|