分块小记
优雅的暴力
前言
如果对于一个序列,如果要求和。一个个地处理需要
分块就是一个折中的办法.可以做一些线段树没法做的事情.
区间加区间和
下面讲解区间加区间和的思路.
假设块长度为
如果现在要给
如果区间覆盖了整个块,直接
如果不是,直接在原数列上进行修改,即暴力。
查询的时候也是一样的.
如果区间覆盖了整个块,直接
如果不是,直接暴力求和.
代码(luogu P3372)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+10;
int a[N],id[N];
int len;
int s[N], tag[N];
#define l(i) ((i)*(len-1)+1)
#define r(i) (min((i)*len,n))
void bupd(int l,int r,int c) {
for(int i=l;i<=r;i++) {
a[i]+=c,s[id[i]]+=c;
}
}
void upd(int l,int r,int c) {
if(id[l] == id[r]) {
bupd(l,r,c);
return ;
}
bupd(l,r(id[l])),bupd(l(id[r]),r);
for(int i=id[l]+1;i<id[r];i++) {
tag[i] += c, s[i] += len*c;
}
}
void bqry(int l,int r,int mod) {
int p = 0;
for(int i=l;i<=r;i++) {
(p += a[i] + tag[id[i]]) %= mod;
}
return p;
}
int query(int l,int r,int mod) {
int ans = 0;
if(id[l] == id[r]) {
return bqry(l,r,mod);
}
(ans += bqry(l,r[id[l]],mod) + bqry(l(id[r]),r,mod))%=mod;
for(int i=id[l]+1;i<id[r];i++) {
(ans+=s[i])%=mod;
}
return ans%mod;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n; cin>>n;
len = sqrt(n);
for(int i=1;i<=n;i++) {
cin>>a[i];
id[i] = (i-1)/len + 1;
s[id[i]] += a[i];
}
while(n--) {
int o,l,r,k;
cin>>o>>l>>r>>k;
if(o==0) upd(l,r,k);
else cout<<query(l,r,k+1)<<"\n";
}
return 0;
}
本文作者:cjrqwq
本文链接:https://www.cnblogs.com/yfzqwq/p/18080228
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步