分块
将区间长度为n的数组分成sqrt (n)个块,每块的大小是sqrt (n)。
对区间[L,R]进行操作:
如果在一个块里面,暴力更新即可。O(sqrt n)级别。
不在一个块里面:
开头一部分,暴力更新,O(sqrt n)级别。
结尾一部分,暴力更新,O(sqrt n)级别。
中间连续的块,打一个延迟标记,不用更新到具体的点,O(sqrt n)级别。
b站链接:https://www.bilibili.com/video/av6445624?from=search&seid=17541052966933649532
建立分块
const int maxn=1e6+7;
int n,m;
int num,block;//块数,块的大小
int belong[maxn];//第i个数属于哪一块
int l[maxn],r[maxn];//l[i]表示第i块的最左边的元素,r[i]表示第i块的最右边的元素
int a[maxn];//原数组
int p[maxn];//延迟标记
int d[maxn];//将a数组进行块内排序后的数组
void build()
{
block=sqrt(n);
num=n/block;if(n%block) num++;
for(int i=1;i<=num;i++)
l[i]=(i-1)*block+1,r[i]=i*block;
r[num]=n;
for(int i=1;i<=n;i++)
{
belong[i]=(i-1)/block+1;
d[i]=a[i];
}
for(int i=1;i<=num;i++)
sort(d+l[i],d+r[i]+1);//块内排序
}
单点更新
void update(int x,int y) //单点更新,将第x个的值加y
{
a[x]+=y;
Max[belong[x]]=max(Max[belong[x]],a[x]);
}
区间查询最大值
long long ask(int x,int y) //区间查询,[x,y]的最大值
{
long long ans=0;
if(belong[x]==belong[y])
{
for(int i=x;i<=y;i++)
ans=max(a[i],ans);
return ans;
}
for(int i=x;i<=r[belong[x]];i++)//最前一部分
ans=max(ans,a[i]);
for(int i=belong[x]+1;i<belong[y];i++)//中间完整的块
ans=max(ans,Max[i]);
for(int i=l[belong[y]];i<=y;i++)//最后一部分
ans=max(ans,a[i]);
return ans;
}