分块
写法一:懒!!!!
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, m;
long long a[100005];
long long blng[100005]; // blng[i]代表i这个数是第几块
long long sum[100005]; // sum[i]代表第i块所有数的和
long long delta[100005]; // delta[i]代表第i块整体被加了多少
int siz[100005]; // siz[i]代表第i块有多少个数
int main()
{
scanf("%d %d", &n, &m); // 读入数的个数和操作数量
for (int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
}
int s = sqrt(n); // s为一个块的大小
for (int i = 1; i <= n; i++)
{
blng[i] = (i - 1) / s + 1;
}
for (int i = 1; i <= n; i++)
{
sum[blng[i]] += a[i]; // 看题目是否要求取模(%mod)
siz[blng[i]]++;
}
for (int i = 1; i <= m; i++)
{
int op;
scanf("%d", &op);
if (op == 1)
{ // 修改操作
int l, r, v;
scanf("%d %d %d", &l, &r, &v); // 要把a[l]~a[r]全部 +v
if (blng[l] == blng[r])
{ // 特殊情况,操作范围的左端点、右端点同属一个块内
for (int j = l; j <= r; j++)
{
a[j] += v;
sum[blng[j]] += v;
}
}
else
{
for (int j = l; blng[j] == blng[l]; j++)
{
a[j] += v;
sum[blng[j]] += v;
}
for (int j = blng[l] + 1; j < blng[r]; j++)
{
delta[j] += v;
sum[j] += siz[j] * v; // 分块时无法确定每块都是均匀的s个,所以提前开数组记录长度
}
for (int j = r; blng[j] == blng[r]; j--)
{
a[j] += v;
sum[blng[j]] += v;
}
}
}
else
{
int l, r, ans = 0;
scanf("%d %d", &l, &r); // 询问a[l]~a[r]
if (blng[l] == blng[r])
{
for (int j = l; j <= r; j++)
{
ans += (a[j] + delta[blng[j]]);
}
}
else
{
for (int j = l; blng[j] == blng[l]; j++)
{
ans += (a[j] + delta[blng[j]]);
}
for (int j = blng[l] + 1; j < blng[r]; j++)
{
ans += sum[j];
}
for (int j = r; blng[j] == blng[r]; j--)
{
ans += (a[j] + delta[blng[j]]);
}
}
printf("%d\n", ans);
}
}
return 0;
}
写法二:(懒标记随时下放)
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=100010;
int n,m,a[maxn],s;
int belong[maxn];//belong[i]代表i这个数是第几块
int siz[maxn];//siz[i]代表第i块有几个数
int sum[maxn];//sum[i]代表第i块所有数的和
int delta[maxn];//delta[i]代表第i块整体被加了多少
void push(int i)//把第i块的delta应用到a上
{
if (delta[i] == 0) return;
int l=s*(i-1)+1;
for (int j=l;belong[j] == belong[l]; j++)
a[j] += delta[i];
delta[i]=0;
}
int main()
{
cin >> n >> m;//读入数的个数和操作数量
for (int i=1;i<=n;i++)
cin >> a[i];
s=sqrt(n);//s是一个块的大小
for (int i=1;i<=n;i++)
belong[i] = (i-1)/s+1;
for (int i=1;i<=n;i++)
sum[belong[i]] += a[i], siz[belong[i]] ++;
for (int i=1;i<=m;i++)
{
int opt;
cin >> opt;
if (opt==1)//修改操作
{
int l,r,v;
cin >> l >> r >> v;//要把a[l]~a[r]全部+v
push(l);push(r);
if (belong[l] == belong[r])
{
for (int j=l;j<=r;j++)
{
a[j] += v;
sum[belong[j]] += v;
}
}
else
{
for (int j=l;belong[j] == belong[l];j++)
{
a[j] += v;
sum[belong[j]] += v;
}
for (int j=belong[l]+1;j<belong[r];j++)
{
delta[j] += v;
sum[j] += siz[j]*v;
}
for (int j=r;belong[j] == belong[r];j--)
{
a[j] += v;
sum[belong[j]] += v;
}
}
}
else
{
int l,r,ans=0;
cin >> l >> r;//询问a[l]~a[r]
push(l);push(r);
if (belong[l] == belong[r])
{
for (int j=l;j<=r;j++)
ans += a[j];
}
else
{
for (int j=l;belong[j] == belong[l];j++)
ans += a[j];
for (int j=belong[l]+1;j<belong[r];j++)
ans += sum[j];
for (int j=r;belong[j] == belong[r];j--)
ans += a[j];
}
cout << ans << endl;
}
}
return 0;
}

浙公网安备 33010602011771号