一直以为分块很高端,学完之后发现其实很简单了
分块查找是折半查找和顺序查找的一种改进方法,分块查找由于只要求索引表是有序的,对块内节点没有排序要求,因此特别适合于节点动态变化的情况。
分块就是将n个数分为每段有√n个数的多个区间,这样我们就可以在几乎O(√n)的时间内完成查找
分块模版
int block,num,belong[100100],le[100100],ri[100100],n;
long long a[100100],max_sum[10100];
void build()
{ int i,j,k;
block=sqrt(n);
num=n/block;
if(n%block)num++;
for(i=1;i<=num;i++)
le[i]=ri[i-1]+1,
ri[i]=ri[i-1]+block;
if(ri[num]>n)ri[num]=n;
for(i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
for(i=1;i<=num;i++)
for(j=le[i];j<=ri[i];j++)
max_sum[i]=max(max_sum[i],a[j]);
}
例题
http://acm.uestc.edu.cn/#/problem/show/1324卿学姐与公主
分块裸题,维护每一块的最大值
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int block,num,belong[100100],le[100100],ri[100100],n;
long long a[100100],max_sum[10100];
void build()
{ int i,j,k;
block=sqrt(n);
num=n/block;
if(n%block)num++;
for(i=1;i<=num;i++)
le[i]=ri[i-1]+1,
ri[i]=ri[i-1]+block;
if(ri[num]>n)ri[num]=n;
for(i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
for(i=1;i<=num;i++)
for(j=le[i];j<=ri[i];j++)
max_sum[i]=max(max_sum[i],a[j]);
}
void update(int p,int x)
{ a[p]+=x;
max_sum[belong[p]]=max(max_sum[belong[p]],a[p]);
}
long long ask(int L,int R)
{ int i,j,k;
long long maxn=0;
if(belong[L]==belong[R]){
for(i=L;i<=R;i++)
maxn=max(maxn,a[i]);
return maxn;
}
else {
for(i=L;i<=ri[belong[L]];i++)
maxn=max(maxn,a[i]);
for(i=belong[L]+1;i<=belong[R]-1;i++)
maxn=max(maxn,max_sum[i]);
for(i=le[belong[R]];i<=R;i++)
maxn=max(maxn,a[i]);
return maxn;
}
}
int main()
{ int q,i,j,k,x,y,p;
cin>>n>>q;
build();
for(i=1;i<=q;i++){
scanf("%d%d%d",&k,&p,&x);
if(k==1)update(p,x);
else printf("%lld
",ask(p,x));
}
return 0;
}