专题训练之分块
推荐博客:http://hzwer.com/8053.html
分块入门题库:https://loj.ac/problems/search?keyword=%E5%88%86%E5%9D%97
分块1:给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const int maxn=5e4+10; 7 const int maxm=1e3+10; 8 int a[maxn],belong[maxn]; 9 int atag[maxm]; 10 int n,sz; 11 12 void add(int l,int r,int c) 13 { 14 for ( int i=l;i<=min(belong[l]*sz,r);i++ ) a[i]+=c; 15 if ( belong[l]!=belong[r] ) { 16 for ( int i=(belong[r]-1)*sz+1;i<=r;i++ ) a[i]+=c; 17 } 18 for ( int i=belong[l]+1;i<=belong[r]-1;i++ ) atag[i]+=c; 19 } 20 21 int main() 22 { 23 int i,j,k,opt,l,r,c; 24 while ( scanf("%d",&n)!=EOF ) { 25 sz=sqrt(n); 26 for ( i=1;i<=n;i++ ) { 27 scanf("%d",&a[i]); 28 belong[i]=(i-1)/sz+1; 29 } 30 memset(atag,0,sizeof(atag)); 31 for ( i=1;i<=n;i++ ) { 32 scanf("%d%d%d%d",&opt,&l,&r,&c); 33 if ( opt==0 ) add(l,r,c); 34 else if ( opt==1 ) printf("%d\n",a[r]+atag[belong[r]]); 35 } 36 } 37 return 0; 38 }
(LOJ6277)https://loj.ac/problem/6277
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 typedef long long ll; 7 const ll maxn=5e4+10; 8 const ll maxm=1e3+10; 9 ll a[maxn],belong[maxn]; 10 ll atag[maxm]; 11 ll n,sz; 12 13 void add(ll l,ll r,ll c) 14 { 15 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) a[i]+=c; 16 if ( belong[l]!=belong[r] ) { 17 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) a[i]+=c; 18 } 19 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) atag[i]+=c; 20 } 21 22 int main() 23 { 24 ll i,j,k,opt,l,r,c; 25 while ( scanf("%lld",&n)!=EOF ) { 26 sz=sqrt(n); 27 for ( i=1;i<=n;i++ ) { 28 scanf("%lld",&a[i]); 29 belong[i]=(i-1)/sz+1; 30 } 31 memset(atag,0,sizeof(atag)); 32 for ( i=1;i<=n;i++ ) { 33 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 34 if ( opt==0 ) add(l,r,c); 35 else if ( opt==1 ) printf("%lld\n",a[r]+atag[belong[r]]); 36 } 37 } 38 return 0; 39 }
分块2:给出一个长为 n 的数列,以及 n个操作,操作涉及区间加法,询问区间内小于某个值 x 的元素个数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<vector> 6 using namespace std; 7 const int maxn=5e4+10; 8 const int maxm=505; 9 int a[maxn],belong[maxn]; 10 int atag[maxm]; 11 vector<int>G[maxm]; 12 int n,sz; 13 14 void reset(int x) 15 { 16 G[x].clear(); 17 for ( int i=(x-1)*sz+1;i<=min(x*sz,n);i++ ) G[x].push_back(a[i]); 18 sort(G[x].begin(),G[x].end()); 19 } 20 21 void add(int l,int r,int c) 22 { 23 for ( int i=l;i<=min(belong[l]*sz,r);i++ ) a[i]+=c; 24 reset(belong[l]); 25 if ( belong[l]!=belong[r] ) { 26 for ( int i=(belong[r]-1)*sz+1;i<=r;i++ ) a[i]+=c; 27 reset(belong[r]); 28 } 29 for ( int i=belong[l]+1;i<=belong[r]-1;i++ ) atag[i]+=c; 30 } 31 32 int query(int l,int r,int c) 33 { 34 int ans=0; 35 for ( int i=l;i<=min(belong[l]*sz,r);i++ ) { 36 if ( a[i]+atag[belong[l]]<c ) ans++; 37 } 38 if ( belong[l]!=belong[r] ) { 39 for ( int i=(belong[r]-1)*sz+1;i<=r;i++ ) { 40 if ( a[i]+atag[belong[r]]<c ) ans++; 41 } 42 } 43 for ( int i=belong[l]+1;i<=belong[r]-1;i++ ) { 44 int x=c-atag[i]; 45 ans+=lower_bound(G[i].begin(),G[i].end(),x)-G[i].begin(); 46 } 47 return ans; 48 } 49 50 int main() 51 { 52 int i,j,k,l,r,c,opt; 53 while ( scanf("%d",&n)!=EOF ) { 54 sz=sqrt(n); 55 memset(atag,0,sizeof(atag)); 56 for ( i=1;i<=n/sz+1;i++ ) G[i].clear(); 57 for ( i=1;i<=n;i++ ) { 58 scanf("%d",&a[i]); 59 belong[i]=(i-1)/sz+1; 60 G[belong[i]].push_back(a[i]); 61 } 62 for ( i=1;i<=belong[n];i++ ) sort(G[i].begin(),G[i].end()); 63 for ( i=1;i<=n;i++ ) { 64 scanf("%d%d%d%d",&opt,&l,&r,&c); 65 if ( opt==0 ) add(l,r,c); 66 else if ( opt==1 ) printf("%d\n",query(l,r,c*c)); 67 } 68 } 69 return 0; 70 }
(LOJ6278)https://loj.ac/problem/6278
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<vector> 6 using namespace std; 7 typedef long long ll; 8 const ll maxn=5e4+10; 9 const ll maxm=505; 10 ll a[maxn],belong[maxn]; 11 ll atag[maxm]; 12 vector<ll>G[maxm]; 13 ll n,sz; 14 15 void reset(ll x) 16 { 17 G[x].clear(); 18 for ( ll i=(x-1)*sz+1;i<=min(x*sz,n);i++ ) G[x].push_back(a[i]); 19 sort(G[x].begin(),G[x].end()); 20 } 21 22 void add(ll l,ll r,ll c) 23 { 24 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) a[i]+=c; 25 reset(belong[l]); 26 if ( belong[l]!=belong[r] ) { 27 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) a[i]+=c; 28 reset(belong[r]); 29 } 30 for ( int i=belong[l]+1;i<=belong[r]-1;i++ ) atag[i]+=c; 31 } 32 33 int query(ll l,ll r,ll c) 34 { 35 int ans=0; 36 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) { 37 if ( a[i]+atag[belong[l]]<c ) ans++; 38 } 39 if ( belong[l]!=belong[r] ) { 40 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 41 if ( a[i]+atag[belong[r]]<c ) ans++; 42 } 43 } 44 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) { 45 ll x=c-atag[i]; 46 ans+=lower_bound(G[i].begin(),G[i].end(),x)-G[i].begin(); 47 } 48 return ans; 49 } 50 51 int main() 52 { 53 ll i,j,k,l,r,c,opt; 54 while ( scanf("%lld",&n)!=EOF ) { 55 sz=sqrt(n); 56 memset(atag,0,sizeof(atag)); 57 for ( i=1;i<=n/sz+1;i++ ) G[i].clear(); 58 for ( i=1;i<=n;i++ ) { 59 scanf("%lld",&a[i]); 60 belong[i]=(i-1)/sz+1; 61 G[belong[i]].push_back(a[i]); 62 } 63 for ( i=1;i<=belong[n];i++ ) sort(G[i].begin(),G[i].end()); 64 for ( i=1;i<=n;i++ ) { 65 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 66 if ( opt==0 ) add(l,r,c); 67 else if ( opt==1 ) printf("%lld\n",query(l,r,c*c)); 68 } 69 } 70 return 0; 71 }
分块3:给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的前驱(比其小的最大元素)。
可以用set维护,因为在set中操作比在普通的数组中操作更加耗时,所以这时候可以自定义控制每个块的sz的大小,进而使得块的数量更少,从而降低一些时间复杂度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<set> 6 using namespace std; 7 const int maxn=1e5+10; 8 const int maxm=1e3+10; 9 int a[maxn],belong[maxn]; 10 int atag[maxm]; 11 int n,sz; 12 set<int>st[maxm]; 13 14 void add(int l,int r,int c) 15 { 16 for ( int i=l;i<=min(belong[l]*sz,r);i++ ) { 17 st[belong[l]].erase(a[i]); 18 a[i]+=c; 19 st[belong[l]].insert(a[i]); 20 } 21 if ( belong[l]!=belong[r] ) { 22 for ( int i=(belong[r]-1)*sz+1;i<=r;i++ ) { 23 st[belong[r]].erase(a[i]); 24 a[i]+=c; 25 st[belong[r]].insert(a[i]); 26 } 27 } 28 for ( int i=belong[l]+1;i<=belong[r]-1;i++ ) atag[i]+=c; 29 } 30 31 int query(int l,int r,int c) 32 { 33 int ans=-1; 34 for ( int i=l;i<=min(belong[l]*sz,r);i++ ) { 35 int val=a[i]+atag[belong[l]]; 36 if ( val<c ) ans=max(val,ans); 37 } 38 if ( belong[l]!=belong[r] ) { 39 for ( int i=(belong[r]-1)*sz+1;i<=r;i++ ) { 40 int val=a[i]+atag[belong[r]]; 41 if ( val<c ) ans=max(val,ans); 42 } 43 } 44 for ( int i=belong[l]+1;i<=belong[r]-1;i++ ) { 45 int x=c-atag[i]; 46 set<int>::iterator it=st[i].lower_bound(x); 47 if ( it==st[i].begin() ) continue; 48 --it; 49 ans=max(ans,*it+atag[i]); 50 } 51 return ans; 52 } 53 54 int main() 55 { 56 int i,j,k,x,y,z,l,r,c,opt; 57 while ( scanf("%d",&n)!=EOF ) { 58 sz=sqrt(n); 59 for ( i=1;i<=n/sz+1;i++ ) st[i].clear(); 60 memset(atag,0,sizeof(atag)); 61 for ( i=1;i<=n;i++ ) { 62 scanf("%d",&a[i]); 63 belong[i]=(i-1)/sz+1; 64 st[belong[i]].insert(a[i]); 65 } 66 for ( i=1;i<=n;i++ ) { 67 scanf("%d%d%d%d",&opt,&l,&r,&c); 68 if ( opt==0 ) add(l,r,c); 69 else if ( opt==1 ) printf("%d\n",query(l,r,c)); 70 } 71 } 72 return 0; 73 }
(LOJ6279)https://loj.ac/problem/6279
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<set> 6 using namespace std; 7 typedef long long ll; 8 const ll maxn=1e5+10; 9 const ll maxm=105; 10 ll a[maxn],belong[maxn]; 11 ll atag[maxm]; 12 ll n,sz; 13 set<ll>st[maxm]; 14 15 void add(ll l,ll r,ll c) 16 { 17 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) { 18 st[belong[l]].erase(a[i]); 19 a[i]+=c; 20 st[belong[l]].insert(a[i]); 21 } 22 if ( belong[l]!=belong[r] ) { 23 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 24 st[belong[r]].erase(a[i]); 25 a[i]+=c; 26 st[belong[r]].insert(a[i]); 27 } 28 } 29 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) atag[i]+=c; 30 } 31 32 ll query(ll l,ll r,ll c) 33 { 34 ll ans=-1; 35 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) { 36 ll val=a[i]+atag[belong[l]]; 37 if ( val<c ) ans=max(val,ans); 38 } 39 if ( belong[l]!=belong[r] ) { 40 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 41 ll val=a[i]+atag[belong[r]]; 42 if ( val<c ) ans=max(val,ans); 43 } 44 } 45 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) { 46 ll x=c-atag[i]; 47 set<ll>::iterator it=st[i].lower_bound(x); 48 if ( it==st[i].begin() ) continue; 49 --it; 50 ans=max(ans,*it+atag[i]); 51 } 52 return ans; 53 } 54 55 int main() 56 { 57 ll i,j,k,x,y,z,l,r,c,opt; 58 while ( scanf("%lld",&n)!=EOF ) { 59 sz=1000; 60 for ( i=1;i<=n/sz+1;i++ ) st[i].clear(); 61 memset(atag,0,sizeof(atag)); 62 for ( i=1;i<=n;i++ ) { 63 scanf("%lld",&a[i]); 64 belong[i]=(i-1)/sz+1; 65 st[belong[i]].insert(a[i]); 66 } 67 for ( i=1;i<=n;i++ ) { 68 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 69 if ( opt==0 ) add(l,r,c); 70 else if ( opt==1 ) printf("%lld\n",query(l,r,c)); 71 } 72 } 73 return 0; 74 }
分块4:给出一个长为n的数列,以及n个操作,操作涉及区间加法,区间求和。
(LOJ6280)https://loj.ac/problem/6280
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 typedef long long ll; 7 const ll maxn=5e4+10; 8 const ll maxm=505; 9 ll a[maxn],belong[maxn]; 10 ll atag[maxm],sum[maxm]; 11 ll n,sz; 12 13 void add(ll l,ll r,ll c) 14 { 15 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) { 16 a[i]+=c; 17 sum[belong[l]]+=c; 18 } 19 if ( belong[l]!=belong[r] ) { 20 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 21 a[i]+=c; 22 sum[belong[r]]+=c; 23 } 24 } 25 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) atag[i]+=c; 26 } 27 28 ll query(ll l,ll r,ll c) 29 { 30 ll mod=c; 31 ll ans=0; 32 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) { 33 ll val=a[i]+atag[belong[l]]; 34 ans=(ans+val)%mod; 35 } 36 if ( belong[l]!=belong[r] ) { 37 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 38 ll val=a[i]+atag[belong[r]]; 39 ans=(ans+val)%mod; 40 } 41 } 42 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) { 43 ans=(ans+sz*atag[i]+sum[i])%mod; 44 } 45 return ans; 46 } 47 48 int main() 49 { 50 ll x,y,z,i,j,k,opt,l,r,c; 51 while ( scanf("%lld",&n)!=EOF ) { 52 sz=sqrt(n); 53 memset(atag,0,sizeof(atag)); 54 memset(sum,0,sizeof(sum)); 55 for ( i=1;i<=n;i++ ) { 56 scanf("%lld",&a[i]); 57 belong[i]=(i-1)/sz+1; 58 sum[belong[i]]+=a[i]; 59 } 60 for ( i=1;i<=n;i++ ) { 61 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 62 if ( opt==0 ) add(l,r,c); 63 else if ( opt==1 ) printf("%lld\n",query(l,r,c+1)%(c+1)); 64 } 65 } 66 return 0; 67 }
分块5:给出一个长为n的数列,以及n个操作,操作涉及区间开方,区间求和。
(LOJ6281)https://loj.ac/problem/6281
设置一个bool型的vis数组标记该块是否还能继续更新。将分块4中的加法/乘法操作改成立方操作。对于完全格的更新,则需要reset操作,因为范围的原因,在较小的开放次数内一个格子内的所有数变会变得不可更新。对于非完全格则直接暴力更新即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 typedef long long ll; 7 const ll maxn=5e4+10; 8 const ll maxm=255; 9 ll a[maxn],belong[maxn]; 10 ll sum[maxm]; 11 bool vis[maxm]; 12 ll n,sz; 13 14 void reset(ll x) 15 { 16 vis[x]=false; 17 sum[x]=0; 18 for ( ll i=(x-1)*sz+1;i<=min(n,x*sz);i++ ) { 19 a[i]=sqrt(a[i]); 20 sum[x]+=a[i]; 21 if ( a[i]>1 ) vis[x]=true; 22 } 23 } 24 25 void update(ll l,ll r) 26 { 27 if ( vis[belong[l]] ) { 28 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) { 29 sum[belong[l]]-=a[i]; 30 a[i]=sqrt(a[i]); 31 sum[belong[l]]+=a[i]; 32 } 33 } 34 if ( belong[l]!=belong[r] ) { 35 if ( vis[belong[r]] ) { 36 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 37 sum[belong[r]]-=a[i]; 38 a[i]=sqrt(a[i]); 39 sum[belong[r]]+=a[i]; 40 } 41 } 42 } 43 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) { 44 if ( vis[i] ) reset(i); 45 } 46 } 47 48 ll query(ll l,ll r) 49 { 50 int ans=0; 51 for ( ll i=l;i<=min(belong[l]*sz,r);i++ ) ans+=a[i]; 52 if ( belong[l]!=belong[r] ) { 53 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) ans+=a[i]; 54 } 55 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) ans+=sum[i]; 56 return ans; 57 } 58 59 int main() 60 { 61 ll x,y,z,i,j,k,l,r,c,opt; 62 while ( scanf("%lld",&n)!=EOF ) { 63 memset(sum,0,sizeof(sum)); 64 memset(vis,false,sizeof(vis)); 65 sz=sqrt(n); 66 for ( i=1;i<=n;i++ ) { 67 scanf("%lld",&a[i]); 68 belong[i]=(i-1)/sz+1; 69 sum[belong[i]]+=a[i]; 70 if ( a[i]>1 ) vis[belong[i]]=true; 71 } 72 for ( i=1;i<=n;i++ ) { 73 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 74 if ( opt==0 ) update(l,r); 75 else printf("%lld\n",query(l,r)); 76 } 77 } 78 return 0; 79 }
分块6:给出一个长为n的数列,以及n个操作,操作涉及单点插入,单点询问,数据随机生成。
用vecot存每一个块中的元素,这样可以在每一块的特定位置插入一个数。当一个块中数的数量过大时则考虑重构每个快
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<vector> 6 using namespace std; 7 const int maxn=1e5+10; 8 const int maxm=355; 9 int a[maxn],n,sz,m; 10 vector<int>ve[maxm]; 11 int st[maxn*2],top; 12 13 pair<int,int> query(int b) 14 { 15 int x=1; 16 while ( b>ve[x].size() ) { 17 b-=ve[x].size(); 18 x++; 19 } 20 return make_pair(x,b-1); 21 } 22 23 void rebuild() 24 { 25 top=0; 26 for ( int i=1;i<=m;i++ ) { 27 for ( vector<int>::iterator it=ve[i].begin();it!=ve[i].end();it++ ) { 28 st[++top]=*it; 29 } 30 ve[i].clear(); 31 } 32 int sz2=sqrt(top); 33 for ( int i=1;i<=top;i++ ) { 34 ve[(i-1)*sz2+1].push_back(st[i]); 35 } 36 m=(top-1)/sz2+1; 37 } 38 39 void insert(int a,int b) 40 { 41 pair<int,int>t=query(a); 42 ve[t.first].insert(ve[t.first].begin()+t.second,b); 43 if ( ve[t.first].size()>20*sz ) rebuild(); 44 } 45 46 int main() 47 { 48 int x,y,z,l,r,c,opt,i,j,k; 49 while ( scanf("%d",&n)!=EOF ) { 50 sz=sqrt(n); 51 for ( i=1;i<=(n-1)/sz+1;i++ ) ve[i].clear(); 52 for ( i=1;i<=n;i++ ) { 53 scanf("%d",&a[i]); 54 ve[(i-1)/sz+1].push_back(a[i]); 55 } 56 m=(n-1)/sz+1; 57 for ( i=1;i<=n;i++ ) { 58 scanf("%d%d%d%d",&opt,&l,&r,&c); 59 if ( opt==0 ) insert(l,r); 60 else if ( opt==1 ) { 61 pair<int,int>t=query(r); 62 printf("%d\n",ve[t.first][t.second]); 63 } 64 } 65 } 66 return 0; 67 }
(LOJ6282)https://loj.ac/problem/6282
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<vector> 6 using namespace std; 7 typedef long long ll; 8 const ll maxn=2e5+10; 9 const ll maxm=1005; 10 ll n,sz,top,m; 11 ll a[maxn],v[maxn]; 12 vector<ll>ve[maxm]; 13 14 pair<ll,ll> query(ll r) 15 { 16 ll x=1; 17 while ( r>ve[x].size() ) { 18 r-=ve[x].size(); 19 x++; 20 } 21 return make_pair(x,r-1); 22 } 23 24 void rebuild() 25 { 26 top=0; 27 for ( ll i=1;i<=m;i++ ) { 28 for ( vector<ll>::iterator it=ve[i].begin();it!=ve[i].end();it++ ) { 29 v[++top]=*it; 30 } 31 ve[i].clear(); 32 } 33 sz=sqrt(top); 34 for ( ll i=1;i<=top;i++ ) { 35 ve[(i-1)/sz+1].push_back(v[i]); 36 } 37 m=(top-1)/sz+1; 38 } 39 40 void insert(ll l,ll r) 41 { 42 pair<ll,ll>t=query(l); 43 ve[t.first].insert(ve[t.first].begin()+t.second,r); 44 if ( ve[t.first].size()>sz*20 ) rebuild(); 45 } 46 47 int main() 48 { 49 ll i,j,k,x,y,z,l,r,c,opt; 50 while ( scanf("%lld",&n)!=EOF ) { 51 sz=sqrt(n); 52 for ( i=1;i<=(n-1)/sz+1;i++ ) ve[i].clear(); 53 for ( i=1;i<=n;i++ ) { 54 scanf("%lld",&a[i]); 55 ve[(i-1)/sz+1].push_back(a[i]); 56 } 57 m=(n-1)/sz+1; 58 for ( i=1;i<=n;i++ ) { 59 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 60 if ( opt==0 ) insert(l,r); 61 else { 62 pair<int,int>t=query(r); 63 printf("%lld\n",ve[t.first][t.second]); 64 } 65 } 66 } 67 return 0; 68 }
分块7:给出一个长为n的数列,以及n个操作,操作涉及区间乘法,区间加法,单点询问。
注意:在暴力更新一个不完整块前先reset该块(即:将该块的乘和加先进行操作)。设置两个数组一个保存加,另一个保存乘。对于加法操作只需要在加法数组中加,对于乘法操作则加法和乘法数组都需要进行操作,在操作时都需要及时取模。
(LOJ6283)https://loj.ac/problem/6283
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 typedef long long ll; 7 const ll maxn=1e5+10; 8 const ll maxm=510; 9 const ll mod=10007; 10 ll n,sz; 11 ll a[maxn],belong[maxn]; 12 ll atag[maxm],mtag[maxm]; 13 14 void reset(ll x) 15 { 16 for ( ll i=(belong[x]-1)*sz+1;i<=min(n,belong[x]*sz);i++ ) { 17 a[i]=(a[i]*mtag[belong[x]]+atag[belong[x]])%mod; 18 } 19 mtag[belong[x]]=1; 20 atag[belong[x]]=0; 21 } 22 23 void update(ll opt,ll l,ll r,ll c) 24 { 25 reset(l); 26 for ( ll i=l;i<=min(r,belong[l]*sz);i++ ) { 27 if ( opt==0 ) a[i]+=c; 28 else a[i]*=c; 29 a[i]%=mod; 30 } 31 if ( belong[l]!=belong[r] ) { 32 reset(r); 33 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 34 if ( opt==0 ) a[i]+=c; 35 else a[i]*=c; 36 a[i]%=mod; 37 } 38 } 39 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) { 40 if ( opt==0 ) atag[i]=(atag[i]+c)%mod; 41 else { 42 atag[i]=(atag[i]*c)%mod; 43 mtag[i]=(mtag[i]*c)%mod; 44 } 45 } 46 } 47 48 int main() 49 { 50 ll x,y,z,i,j,k,l,r,c,opt,val; 51 while ( scanf("%lld",&n)!=EOF ) { 52 sz=sqrt(n); 53 for ( i=1;i<=n;i++ ) { 54 scanf("%lld",&a[i]); 55 belong[i]=(i-1)/sz+1; 56 } 57 for ( i=1;i<=belong[n];i++ ) { 58 atag[i]=0; 59 mtag[i]=1; 60 } 61 for ( i=1;i<=n;i++ ) { 62 scanf("%lld%lld%lld%lld",&opt,&l,&r,&c); 63 if ( opt==2 ) { 64 val=(mtag[belong[r]]*a[r]+atag[belong[r]])%mod; 65 printf("%lld\n",val); 66 } 67 else update(opt,l,r,c); 68 } 69 } 70 return 0; 71 }
分块8:给出一个长为n的数列,以及n个操作,操作涉及区间询问等于一个数c的元素,并将这个区间的所有元素改为c。
只需要设置一个bool型数组判断该区间是否处于被整体修改状态,设置tag数组记录修改后的值。当修改的区间为完全区间时,只需要修改块的信息。当区间为不完全区间时,需要reset一下该块(将该块保存的信息传递到每个块上),然后进行暴力的逐一修改
(LOJ6284)https://loj.ac/problem/6284
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<vector> 5 #include<algorithm> 6 using namespace std; 7 typedef long long ll; 8 const ll maxn=1e5+10; 9 const ll maxm=355; 10 ll n,sz,a[maxn],belong[maxn]; 11 bool vis[maxm]; 12 ll tag[maxm]; 13 14 void reset(int x) 15 { 16 if ( !vis[x] ) return; 17 for ( int i=(x-1)*sz+1;i<=x*sz;i++ ) a[i]=tag[x]; 18 } 19 20 void update(ll l,ll r,ll c) 21 { 22 reset(belong[l]); 23 vis[belong[l]]=false; 24 for ( ll i=l;i<=min(r,belong[l]*sz);i++ ) a[i]=c; 25 if ( belong[l]!=belong[r] ) { 26 reset(belong[r]); 27 vis[belong[r]]=false; 28 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) a[i]=c; 29 } 30 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) { 31 tag[i]=c; 32 vis[i]=true; 33 } 34 } 35 36 ll query(ll l,ll r,ll c) 37 { 38 ll ans=0; 39 if ( !vis[belong[l]] ) { 40 for ( ll i=l;i<=min(r,belong[l]*sz);i++ ) { 41 if ( a[i]==c ) ans++; 42 } 43 } 44 else { 45 if ( tag[belong[l]]==c ) { 46 ll x=min(r,belong[l]*sz); 47 ans+=(x-l+1); 48 } 49 } 50 if ( belong[l]!=belong[r] ) { 51 if ( !vis[belong[r]] ) { 52 for ( ll i=(belong[r]-1)*sz+1;i<=r;i++ ) { 53 if ( a[i]==c ) ans++; 54 } 55 } 56 else { 57 if ( tag[belong[r]]==c ) { 58 ans+=(r-(belong[r]-1)*sz); 59 } 60 } 61 } 62 for ( ll i=belong[l]+1;i<=belong[r]-1;i++ ) { 63 if ( !vis[i] ) { 64 for ( ll j=(i-1)*sz+1;j<=i*sz;j++ ) { 65 if ( a[j]==c ) ans++; 66 } 67 } 68 else { 69 if ( tag[i]==c ) ans+=sz; 70 } 71 } 72 return ans; 73 } 74 75 int main() 76 { 77 ll i,j,k,x,y,z,l,r,c,opt; 78 while ( scanf("%lld",&n)!=EOF ) { 79 sz=sqrt(n); 80 memset(vis,false,sizeof(vis)); 81 for ( i=1;i<=n;i++ ) { 82 scanf("%lld",&a[i]); 83 belong[i]=(i-1)/sz+1; 84 } 85 for ( i=1;i<=n;i++ ) { 86 scanf("%lld%lld%lld",&l,&r,&c); 87 printf("%lld\n",query(l,r,c)); 88 update(l,r,c); 89 } 90 } 91 return 0; 92 }