分块讲解
临近NOIP,我要复习各种学过的算法,先从暴力开始吧!
分块就是把一个待求的序列分成√n块.之后暴力查找。分整块和散块两部分。所有信息在当前结点和块内同时维护。每次查询O(3*√n)。修改不一定。一般是O(1)--O(√n) 之间。
这就是分块,原理及其简单。但写起来需要考虑一些细节。
比如:洛谷P1816 忠诚 求区间最小值问题。
我们还是可以把查询分成整块和散块两种,预处理每块内最小值与每个数在哪个块。这样方便O(1)查询。
帖代码:
#include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; #define N 100010 int n,Q; int belong[N]; int minn[400]; int a[N]; int block,ans; int query(int x,int y) { int minx=0x3f3f3f3f; for(int i=x;i<=min(belong[x]*block,y);i++) minx=min(minx,a[i]); if(belong[x]!=belong[y]) for(int i=(belong[y]-1)*block+1;i<=y;i++) minx=min(minx,a[i]); for(int i=belong[x]+1;i<belong[y];i++) minx=min(minx,minn[i]); return minx; } int main() { memset(minn,0x3f,sizeof(minn)); scanf("%d%d",&n,&Q); block=sqrt(n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); belong[i]=(i-1)/block+1; minn[belong[i]]=min(a[i],minn[belong[i]]); } for(int i=1;i<=Q;i++) { int x,y; scanf("%d%d",&x,&y); ans=query(x,y); printf("%d ",ans); } }
细节需要自己思考!