推薦博客:http://hzwer.com/8053.html
分塊入門題庫:https://loj.ac/problems/search?keyword=%E5%88%86%E5%9D%97
分塊1:給出一個長為n的數列,以及n個操作,操作涉及區間加法,單點查值。

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

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 的元素個數。

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

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的大小,進而使得塊的數量更少,從而降低一些時間復雜度

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

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

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操作,因為范圍的原因,在較小的開放次數內一個格子內的所有數變會變得不可更新。對於非完全格則直接暴力更新即可

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存每一個塊中的元素,這樣可以在每一塊的特定位置插入一個數。當一個塊中數的數量過大時則考慮重構每個快

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

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

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

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 }