[分块]入门题目
https://blog.csdn.net/keepcoral/article/details/80743559
数列分块入门 1
正确解法:
简单分块,然后区间之外的暴力,区间之内的 lazy 数组标记。
![[分块]入门题目 随笔 第3张 [分块]入门题目 随笔 第3张](https://www.liuyixiang.com/zb_users/theme/Lucky/style/image/grey.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <set> 7 #include <map> 8 #include <vector> 9 #include <cctype> 10 #include <sstream> 11 using namespace std; 12 typedef long long ll; 13 const int inf=0x7fffffff; 14 const int N=50000+100; 15 const int M=5000+10; 16 const double PI=acos(-1.0); 17 int n; 18 ll a[N],lazy[10000]; 19 int op,l,r,c; 20 vector<ll>buck[10000]; 21 int main() 22 { 23 scanf("%d",&n); 24 int b=sqrt(n),m=n; 25 //cout<<b<<endl; 26 for(int i=0;i<n;i++) 27 { 28 scanf("%d",&a[i]); 29 buck[i%b].push_back(a[i]); 30 } 31 while(m--) 32 { 33 scanf("%d %d %d %d",&op,&l,&r,&c); 34 if(op==0) 35 { 36 if(l>0) l--; 37 while(l<r && l%b!=0) a[l++]+=c; 38 while(l<r && r%b!=0) a[--r]+=c; 39 while(l<r) 40 { 41 int kk=l/b; 42 lazy[kk]+=c; 43 l+=b; 44 } 45 } 46 else 47 { 48 r--; 49 printf("%d\n",a[r]+lazy[r/b]); 50 } 51 } 52 53 54 return 0; 55 }View Code
数列分块入门 2
正确解法:
把所有都存进数组vector里面, 然后排序,如果改变一个分块里面的部分值,就再次对块进行更新。
![[分块]入门题目 随笔 第7张 [分块]入门题目 随笔 第7张](https://www.liuyixiang.com/zb_users/theme/Lucky/style/image/grey.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <set> 7 #include <map> 8 #include <vector> 9 #include <cctype> 10 #include <sstream> 11 using namespace std; 12 typedef long long ll; 13 const int inf=0x7fffffff; 14 const int N=50000+100; 15 const int M=5000+10; 16 const double PI=acos(-1.0); 17 int n; 18 ll a[N],lazy[10000]; 19 int blo[N]; 20 int op,l,r,c,b; 21 vector<ll>buck[10000]; 22 void reset(int x) 23 { 24 buck[x].clear(); 25 for(int i=(x-1)*b+1;i<=min(x*b,n);i++) 26 buck[x].push_back(a[i]); 27 sort(buck[x].begin(),buck[x].end()); 28 } 29 void add(int l,int r,int c) 30 { 31 for(int i=l;i<=min(blo[l]*b,r);i++) 32 a[i]+=c; 33 reset(blo[l]); 34 if(blo[l]!=blo[r]) 35 { 36 for(int i=(blo[r]-1)*b+1;i<=r;i++) 37 a[i]+=c; 38 reset(blo[r]); 39 } 40 for(int i=blo[l]+1;i<=blo[r]-1;i++) 41 lazy[i]+=c; 42 } 43 int query(int l,int r,int c) 44 { 45 int ans=0; 46 for(int i=l;i<=min(blo[l]*b,r);i++) 47 if(a[i]+lazy[blo[l]]<c) ans++; 48 if(blo[l]!=blo[r]) 49 { 50 for(int i=(blo[r]-1)*b+1;i<=r;i++) 51 if(a[i]+lazy[blo[r]]<c) ans++; 52 } 53 for(int i=blo[l]+1;i<=blo[r]-1;i++) 54 ans+=lower_bound(buck[i].begin(),buck[i].end(),c-lazy[i])-buck[i].begin(); 55 return ans; 56 } 57 int main() 58 { 59 scanf("%d",&n); 60 b=sqrt(n); 61 for(int i=1;i<=n;i++) 62 { 63 scanf("%lld",&a[i]); 64 blo[i]=(i-1)/b+1; 65 buck[blo[i]].push_back(a[i]); 66 } 67 for(int i=1;i<=blo[n];i++) 68 sort(buck[i].begin(),buck[i].end()); 69 for(int i=1;i<=n;i++) 70 { 71 scanf("%d %d %d %d",&op,&l,&r,&c); 72 if(op==0) add(l,r,c); 73 else 74 printf("%d\n",query(l,r,c*c)); 75 } 76 77 78 return 0; 79 }View Code
数列分块入门 3
正确解法:
这个需要找相对应的元素,而不是元素个数,就用到了set。
![[分块]入门题目 随笔 第11张 [分块]入门题目 随笔 第11张](https://www.liuyixiang.com/zb_users/theme/Lucky/style/image/grey.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <set> 7 #include <map> 8 #include <vector> 9 #include <cctype> 10 #include <sstream> 11 using namespace std; 12 typedef long long ll; 13 const int inf=0x7fffffff; 14 const int N=100000+100; 15 const int M=5000+10; 16 const double PI=acos(-1.0); 17 int n; 18 ll a[N],lazy[10000]; 19 int blo[N]; 20 int op,l,r,c,m; 21 set<ll>buck[10000]; 22 void reset(int x) 23 { 24 buck[x].clear(); 25 for(int i=(x-1)*m+1;i<=min(x*m,n);i++) 26 buck[x].insert(a[i]); 27 } 28 void add(int l,int r,int c) 29 { 30 for(int i=l;i<=min(blo[l]*m,r);i++) 31 a[i]+=c; 32 reset(blo[l]); 33 if(blo[l]!=blo[r]) 34 { 35 for(int i=(blo[r]-1)*m+1;i<=r;i++) 36 a[i]+=c; 37 reset(blo[r]); 38 } 39 for(int i=blo[l]+1;i<=blo[r]-1;i++) 40 lazy[i]+=c; 41 } 42 ll query(int l,int r,int c) 43 { 44 ll kk=-1; 45 for(int i=l;i<=min(blo[l]*m,r);i++) 46 if(a[i]+lazy[blo[l]]<c) 47 kk=max(kk,a[i]+lazy[blo[l]]); 48 if(blo[l]!=blo[r]) 49 { 50 for(int i=(blo[r]-1)*m+1;i<=r;i++) 51 if(a[i]+lazy[blo[r]]<c) 52 kk=max(kk,a[i]+lazy[blo[r]]); 53 } 54 for(int i=blo[l]+1;i<=blo[r]-1;i++) 55 { 56 set<ll>::iterator it; 57 it=buck[i].lower_bound(c-lazy[i]); 58 if(it==buck[i].begin()) continue; 59 it--; 60 kk=max(kk,(*it)+lazy[i]); 61 } 62 return kk; 63 } 64 int main() 65 { 66 scanf("%d",&n); 67 m=sqrt(n); 68 for(int i=1;i<=n;i++) 69 { 70 scanf("%lld",&a[i]); 71 blo[i]=(i-1)/m+1; 72 buck[blo[i]].insert(a[i]); 73 } 74 for(int i=1;i<=n;i++) 75 { 76 scanf("%d %d %d %d",&op,&l,&r,&c); 77 if(op==0) add(l,r,c); 78 else 79 printf("%lld\n",query(l,r,c)); 80 } 81 82 83 return 0; 84 }View Code
数列分块入门 4
正确解法:
开一个sum数组就好了,注意的是 整个块相加是 sum[i]+lazy[i]*m;
![[分块]入门题目 随笔 第15张 [分块]入门题目 随笔 第15张](https://www.liuyixiang.com/zb_users/theme/Lucky/style/image/grey.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <set> 7 #include <map> 8 #include <vector> 9 #include <cctype> 10 #include <sstream> 11 using namespace std; 12 typedef long long ll; 13 const int inf=0x7fffffff; 14 const int N=100000+100; 15 const int M=5000+10; 16 const double PI=acos(-1.0); 17 int n; 18 ll a[N],lazy[10000],sum[10000]; 19 int blo[N]; 20 int op,l,r,c,m; 21 set<ll>buck[10000]; 22 void reset(int x) 23 { 24 buck[x].clear(); 25 for(int i=(x-1)*m+1;i<=min(x*m,n);i++) 26 buck[x].insert(a[i]); 27 } 28 void add(int l,int r,int c) 29 { 30 for(int i=l;i<=min(blo[l]*m,r);i++) 31 a[i]+=c; 32 sum[blo[l]]+=(min(blo[l]*m,r)-l+1)*c; 33 //reset(blo[l]); 34 if(blo[l]!=blo[r]) 35 { 36 for(int i=(blo[r]-1)*m+1;i<=r;i++) 37 a[i]+=c; 38 sum[blo[r]]+=(r-(blo[r]-1)*m)*c; 39 //reset(blo[r]); 40 } 41 for(int i=blo[l]+1;i<=blo[r]-1;i++) 42 lazy[i]+=c; 43 } 44 ll query(int l,int r,int c) 45 { 46 ll ans=0; 47 for(int i=l;i<=min(blo[l]*m,r);i++) 48 ans+=(a[i]+lazy[blo[l]])%c; 49 ans%=c; 50 if(blo[l]!=blo[r]) 51 { 52 for(int i=(blo[r]-1)*m+1;i<=r;i++) 53 ans+=(a[i]+lazy[blo[r]])%c; 54 ans%=c; 55 } 56 for(int i=blo[l]+1;i<=blo[r]-1;i++) 57 { 58 ans+=(sum[i]+lazy[i]*m)%c; 59 ans%=c; 60 } 61 return ans; 62 } 63 int main() 64 { 65 scanf("%d",&n); 66 m=sqrt(n); 67 for(int i=1;i<=n;i++) 68 { 69 scanf("%lld",&a[i]); 70 blo[i]=(i-1)/m+1; 71 buck[blo[i]].insert(a[i]); 72 sum[blo[i]]+=a[i]; 73 } 74 for(int i=1;i<=n;i++) 75 { 76 scanf("%d %d %d %d",&op,&l,&r,&c); 77 if(op==0) add(l,r,c); 78 else 79 printf("%lld\n",query(l,r,c+1)); 80 } 81 82 83 return 0; 84 }View Code
数列分块入门 5
正确解法:
每个数最终都会变成0或1,我们暴力每个块,若它的最大值小于等于1,就不必再更新,否则就暴力更新。
![[分块]入门题目 随笔 第19张 [分块]入门题目 随笔 第19张](https://www.liuyixiang.com/zb_users/theme/Lucky/style/image/grey.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <set> 7 #include <map> 8 #include <vector> 9 #include <cctype> 10 #include <sstream> 11 using namespace std; 12 typedef long long ll; 13 const int inf=0x7fffffff; 14 const int N=100000+100; 15 const int M=5000+10; 16 const double PI=acos(-1.0); 17 int n; 18 ll a[N],lazy[10000],sum[10000],maxx[10000]; 19 int blo[N]; 20 int op,l,r,c,m; 21 set<ll>buck[10000]; 22 void reset(int x) 23 { 24 buck[x].clear(); 25 for(int i=(x-1)*m+1;i<=min(x*m,n);i++) 26 buck[x].insert(a[i]); 27 } 28 void rset(int x) 29 { 30 sum[x]=0; 31 maxx[x]=0; 32 for(int i=(x-1)*m+1;i<=min(x*m,n);i++) 33 { 34 sum[x]+=a[i]; 35 maxx[x]=max(maxx[x],a[i]); 36 } 37 } 38 void add(int l,int r,int c) 39 { 40 for(int i=l;i<=min(blo[l]*m,r);i++) 41 a[i]=sqrt(a[i]); 42 rset(blo[l]); 43 //reset(blo[l]); 44 if(blo[l]!=blo[r]) 45 { 46 for(int i=(blo[r]-1)*m+1;i<=r;i++) 47 a[i]=sqrt(a[i]); 48 rset(blo[r]); 49 //reset(blo[r]); 50 } 51 for(int i=blo[l]+1;i<=blo[r]-1;i++) 52 if(maxx[i]>1) 53 { 54 for(int j=(i-1)*m+1;j<=i*m;j++) 55 a[j]=sqrt(a[j]); 56 rset(i); 57 } 58 } 59 ll query(int l,int r,int c) 60 { 61 ll ans=0; 62 for(int i=l;i<=min(blo[l]*m,r);i++) 63 ans+=a[i]; 64 if(blo[l]!=blo[r]) 65 { 66 for(int i=(blo[r]-1)*m+1;i<=r;i++) 67 ans+=a[i]; 68 } 69 for(int i=blo[l]+1;i<=blo[r]-1;i++) 70 { 71 ans+=sum[i]; 72 } 73 return ans; 74 } 75 int main() 76 { 77 scanf("%d",&n); 78 m=sqrt(n); 79 for(int i=1;i<=n;i++) 80 { 81 scanf("%lld",&a[i]); 82 blo[i]=(i-1)/m+1; 83 sum[blo[i]]+=a[i]; 84 maxx[blo[i]]=2; 85 } 86 for(int i=1;i<=n;i++) 87 { 88 scanf("%d %d %d %d",&op,&l,&r,&c); 89 if(op==0) add(l,r,c); 90 else 91 printf("%lld\n",query(l,r,c)); 92 } 93 94 95 return 0; 96 }View Code

更多精彩