#include<bits/stdc++.h>
//luoguP2357
#define int long long
using namespace std;
typedef long long ll;
int n, p, op, l, r;
int len, m;//块长,块个数
ll k;
ll a[200005];
struct blocks{
int l, r;
ll sum;//不包括ch
ll ch;//修改
int len;
int Cls(int stai, int qlen)
{
if (stai + qlen - 1 > n)
len = n - stai + 1;
else
len = qlen;
l = stai, r = stai + len - 1;
for (int i = l;i <= r; ++i)
sum += a[i];
ch = 0;
return r + 1;
}
int Sum()
{
return sum + ch * (r - l + 1);
}
void change(ll k)
{
ch += k;
}
void changePoint(int p, int k)
{
a[p] += k;
sum += k;
}
ll Get(int p)
{
return a[p] + ch;
}
ll GetSum()
{
return sum + ch * (r - l + 1);
}
}blck[2005];
signed main()
{
//freopen("a.in", "r", stdin);
//freopen("my.out", "w", stdout);
scanf("%d%d", &n, &p);
for (int i = 1;i <= n; ++i)
scanf("%lld", a + i);
len = (int)sqrt(n);
for (int i = 1, j = 1;i <= n; i = blck[j].Cls(i, len), ++j) m = j;
blck[0].r = 0;
blck[m + 1].l = n + 1;
for (int t = 1;t <= p; ++t)
{
scanf("%d", &op);
//printf("操作#%d\n", t);
if(op == 1)
{
scanf("%d%d%lld", &l, &r, &k);
//printf("add %d,%d\n", l, r);
int le, li, re, ri;
for (int i = 1; i <= m + 1; ++i){
if (l < blck[i].l)
{
le = blck[i].l;
li = i - 1;
break;
}
if (l == blck[i].l)
{
le = blck[i].l;
li = i;
break;
}
}
for (int i = 1; i <= m; ++i){
if (r < blck[i].r)
{
re = blck[i].l;
ri = i;
break;
}
if (r == blck[i].r)
{
re = blck[i].r;
ri = i;
break;
}
}
//printf("li=%d,ri=%d\n", li, ri);
if (li == ri)
{
for (int i = l;i <= r; ++i)
blck[ri].changePoint(i, k);
//for (int i = 1;i <= m; ++i)
// for (int j = blck[i].l;j <= blck[i].r; ++j)
// printf("%lld\n", blck[i].Get(j));
continue;
}
if (l != le){
for (int i = l;i <= le - 1; ++i)
blck[li].changePoint(i, k);
//printf("左区间非整块区域:%d,%d\n", l, le);
++li;
}
if (r != blck[ri].r){
for (int i = re;i <= r; ++i)
blck[ri].changePoint(i, k);
//printf("右区间非整块区域:%d,%d\n", re, r);
--ri;
}
//printf("区间from %d to %d\n", li, ri);
for (int i = li;i <= ri; ++i)
blck[i].change(k)/*, printf("整块区域:块%d\n", i)*/;
// for (int i = 1;i <= m; ++i)
// for (int j = blck[i].l;j <= blck[i].r; ++j)
// printf("%lld\n", blck[i].Get(j));
}
else if (op == 2){
scanf("%lld", &k);
blck[1].changePoint(1, k);
//for (int i = 1;i <= m; ++i)
// for (int j = blck[i].l;j <= blck[i].r; ++j)
// printf("%lld\n", blck[i].Get(j));
}
else if (op == 3){
scanf("%lld", &k);
blck[1].changePoint(1, -k);
//for (int i = 1;i <= m; ++i)
// for (int j = blck[i].l;j <= blck[i].r; ++j)
// printf("%lld\n", blck[i].Get(j));
}
else if (op == 4){
ll res = 0;
scanf("%d%d", &l, &r);
int le, li, re, ri;
for (int i = 1; i <= m + 1; ++i)
{
if (l < blck[i].l)
{
le = blck[i].l;
li = i;
break;
}
if (l == blck[i].l)
{
le = blck[i].l;
li = i;
break;
}
}
for (int i = 1; i <= m; ++i)
{
if (r < blck[i].r)
{
re = blck[i].l;
ri = i - 1;
break;
}
if (r == blck[i].r)
{
re = blck[i].r;
ri = i;
break;
}
}
if (li == ri)
{
for (int i = l;i <= r; ++i)
res += blck[ri].Get(i);
printf("%lld\n", res);
continue;
}
if (l != le){
//printf("%d-%d\n", l, le);
for (int i = l;i <= le - 1; ++i)
res += blck[li].Get(i);
printf("左区间非整块区域:%d,%d\n", l, le - 1);
//++li;
}
if (r != re){
for (int i = re;i <= r; ++i)
res += blck[ri].Get(i);
printf("右区间非整块区域:%d,%d\n", re, r);
--ri;
}
printf("区间from %d to %d\n", li, ri);
for (int i = li;i <= ri; ++i)
res += blck[i].GetSum()/*, printf("整块区域:块%d +=%lld\n", i, blck[i].GetSum())*/;
//for (int i = 1;i <= m; ++i)
// for (int j = blck[i].l;j <= blck[i].r; ++j)
// printf("%lld\n", blck[i].Get(j));
printf("%lld\n", res);
}
else
{
printf("%lld\n", blck[1].Get(1));
}
}
return 0;
}
蒟蒻调了一下午,60ptsWA,求调 QwQ