分块是一种算法思想,它通过将数据按照一定规模分成若干块,通过讲问题分解为若干个整块统计和某些块内的统计来平衡算法的复杂度。分块一般用来被解决一些看起来可以用但实际上不能二分治结构或者算法解决的问题,一个很显然的例子就是序列上的问题线段树能解决的都是分块能解决的子集(所以我将线段树视为分块的一个进化,如果学了分块再去学线段树会比直接学要简单一些)。但比起二分治结构来说带根号的时间复杂度是它的缺点同时也是它的标志,但需要注意的是带根号的算法并不一定是分块。
前言:
NEED:
1,有一定的暴力经验;
2,有基础数据结构的经验。
YOU CAN GET:
1,一下午切完线段树基础题的力量。
2,区间操作可能会有80分,幸运时是100.
分块的优点:
·短小精悍(一般只有线段树的一半);
·思路简单(因为是暴力么)。
缺点:
速度慢于二叉树,在数据大于10W时可能不能AC(p.s.:但不失为骗分的利器)
插一段 made by lsj 的 PPT
模板:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 const int maxx=1000100,inf=1000000000; 8 int n=0,s=0,c=0,k=0,q=0,w=0; //n为序列长度,S代表块的大小,C为块数 9 int a[maxx],f[maxx]; // a【i】为序列,f[i]代表第i个数属于第几个块 10 int mx[500],zuo[500],you[500]; mx[i]为第i个块的最大值,第i个块所对应的区间为[zuo[i],you[i]] 11 12 void chu() //初始化 13 { 14 s=(int)sqrt((double)n); 15 for(int i=1;i<n;i+=s) 16 { 17 f[i]=++c; 18 for(int j=i+1;j<=i+s-1;j++) 19 { 20 f[j]=f[i]; 21 } 22 zuo[c]=i; 23 you[c]=i+s-1; 24 } 25 if(s>0) 26 if(n%s>0) 27 { 28 zuo[c+1]=you[c]+1; 29 you[++c]=n; 30 for(int i=zuo[c];i<=you[c];i++) f[i]=c; 31 } 32 33 } 34 35 void gai(int x,int v) //赋值 36 { 37 int y=f[x]; 38 a[x]=v; 39 int temp=-1*inf; 40 for(int i=zuo[y];i<=you[y];i++) 41 if(a[i]>temp) 42 temp=a[i]; 43 44 mx[y]=temp; 45 } 46 47 int zui(int l,int r) //查找 48 { 49 int x=f[l],y=f[r],ans=-inf; 50 if(x==y) 51 { 52 for(int i=l;i<=r;i++) 53 if(a[i]>ans) 54 ans=a[i]; 55 return ans; 56 } 57 for(int i=l;i<=you[x];i++) 58 if(a[i]>ans) 59 ans=a[i]; 60 for(int i=x+1;i<y;i++) 61 if(mx[i]>ans) 62 ans=mx[i]; 63 for(int i=zuo[y];i<=r;i++) 64 if(a[i]>ans) 65 ans=a[i]; 66 return ans; 67 } 68 int main() 69 { 70 memset(a,0,sizeof(a)); 71 memset(f,0,sizeof(f)); 72 memset(mx,0,sizeof(mx)); 73 cin>>n; 74 chu(); 75 for(int i=1;i<=n;i++) 76 { 77 cin>>k>>q>>w; 78 if(k==1) gai(q,w); 79 if(k==2) cout<<zui(q,w)<<endl; 80 } 81 return 0; 82 }
另一种整体赋值:
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<iomanip> 8 #include<queue> 9 #include<vector> 10 #include<cstring> 11 using namespace std; 12 const int maxn=1000100,inf=1000000000; 13 int n=0,s=0,c=0,k=0,q=0,w=0; 14 int a[maxn],f[maxn]; 15 int mx[500],zuo[500],you[500],add[maxn]; 16 17 void chu() 18 { 19 s=(int)sqrt((double)n); 20 for(int i=1;i<n;i+=s) 21 { 22 f[i]=++c; 23 for(int j=i+1;j<=i+s-1;j++) 24 { 25 f[j]=f[i]; 26 } 27 zuo[c]=i; 28 you[c]=i+s-1; 29 } 30 if(s>0) 31 if(n%s>0) 32 { 33 zuo[c+1]=you[c]+1; 34 you[++c]=n; 35 for(int i=zuo[c];i<=you[c];i++) f[i]=c; 36 } 37 38 } 39 40 /*void gai(int x,int v) 41 { 42 int y=f[x]; 43 a[x]=v; 44 int temp=-1*inf; 45 for(int i=zuo[y];i<=you[y];i++) 46 if(a[i]>temp) 47 temp=a[i]; 48 49 mx[y]=temp; 50 }*/ 51 52 void gai(int x,int y) 53 { 54 int l=f[x]; 55 int r=f[y]; 56 if(l==r) 57 { 58 for(int i=x;i<=y;i++) 59 { 60 a[i]++; 61 if(a[i]+add[l]>mx[l]) 62 mx[l]=a[i]+add[l]; 63 } 64 return; 65 } 66 for(int i=x;i<=you[l];i++) 67 { 68 a[i]++; 69 if(a[i]+add[l]>mx[l]) 70 mx[l]=a[i]+add[l]; 71 } 72 for(int i=l+1;i<r;i++) 73 { 74 add[i]++; 75 mx[i]++; 76 } 77 for(int i=zuo[r];i<=y;i++) 78 { 79 a[i]++; 80 if(a[i]+add[r]>mx[r]) 81 mx[r]=a[i]+add[r]; 82 } 83 } 84 85 int zui(int l,int r) 86 { 87 int x=f[l],y=f[r],ans=-inf; 88 if(x==y) 89 { 90 for(int i=l;i<=r;i++) 91 if(a[i]+add[x]>ans) 92 ans=a[i]+add[x]; 93 return ans; 94 } 95 for(int i=l;i<=you[x];i++) 96 if(a[i]+add[x]>ans) 97 ans=a[i]+add[x]; 98 for(int i=x+1;i<y;i++) 99 if(mx[i]>ans) 100 ans=mx[i]; 101 for(int i=zuo[y];i<=r;i++) 102 if(a[i]+add[y]>ans) 103 ans=a[i]+add[y]; 104 return ans; 105 } 106 int main() 107 { 108 /*freopen("2.in","r",stdin); 109 freopen("2.out","w",stdout);*/ 110 //ios::sync_with_stdio(false); 111 memset(a,0,sizeof(a)); 112 memset(f,0,sizeof(f)); 113 memset(mx,0,sizeof(mx)); 114 memset(add,0,sizeof(add)); 115 cin>>n; 116 chu(); 117 for(int i=1;i<=n;i++) 118 { 119 cin>>k>>q>>w; 120 if(k==1) gai(q,w); 121 if(k==2) cout<<zui(q,w)<<endl; 122 } 123 return 0; 124 }