标签:
最近在做学长模拟赛的时候发现分块可以的很多部分分,所以就跟着学了分块。
分块其实是一种做题的思路,由于我只是学了一下线性的分块,所以就光说一下线性的吧:其实大体思路就是当我们要对一个规模比较大的问题进行修改或查询的时候,用数据结构不好去维护,但是范围太大又不能用暴力去做,所以我们就可以把这个大的数据分成大约是sqrt(n),但是也不一定.
放一道例题:来自国家队的论文
由于是写论文的人自己出的题没所以没有数据,我就自己拍了一下,我觉得应该是A了,如果有谁拍出了错,记得跟我说一下。。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #include<cmath> int n,m,a[100010]={0},len,N=1,d[400]={0},num[400]={0},influence[400][400]; char ch; int main() { freopen("cin.in","r",stdin); freopen("a.out","w",stdout); int i,j,x,y; scanf("%d%d",&n,&m); for(i=1;i<=n;++i) scanf("%d",&a[i]); len=sqrt(n); while(1){ N+=1; if(N*len==n) break; else if(N*len>n) break; } for(i=1;i<=N;++i) for(j=1;j<=len;++j){ if((i-1)*len+j>n) break; num[i]+=a[(i-1)*len+j]; } if(len==1){ while(m--){ int t,x,y; cin>>t>>x>>y; if(t==1){ for(j=1;j<=n;j+=x) a[j]+=y; } else{ int ans=0; for(j=x;j<=y;++j) ans+=a[j]; cout<<ans<<endl; } } } else{ while(m--){ int t; scanf("%d%d%d",&t,&x,&y); if(t==1){ if(x>=len){ i=1; while(i<=n){ if(i%len==0) num[i/len]+=y; else num[i/len+1]+=y; a[i]+=y;i+=x; } } else d[x]+=y; } else{ int ans=0,l,r,ll,rr; l=(x%len==0)?x/len:(x/len+1); r=(y%len==0)?(y/len):(y/len+1); ll=len*(l-1)+1==x?l:l+1; rr=y%len==0?r:r-1; for(i=ll;i<=rr;++i) ans+=num[i]; if(ll<=rr){ if(l<ll) for(i=x;i<=l*len;++i) ans+=a[i]; if(r>rr) for(i=rr*len+1;i<=y;++i) ans+=a[i]; } else{ for(i=x;i<=y;++i) ans+=a[i]; } for(i=1;i<=len;++i){ int r1,r2; r1=x/i; if(x%i>1) r1+=1; r2=y/i; if(y%i>=1) r2+=1; ans+=(r2-r1)*d[i]; if(i==1) ans+=d[i]; } printf("%d\n",ans); } } } }
标签:
原文地址:http://blog.csdn.net/fzhvampire/article/details/44728457