专题训练之分块

推荐博客: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
",a[r]+atag[belong[r]]);
35         }
36     }
37     return 0;
38 }
分块1

(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
",a[r]+atag[belong[r]]);
36         }
37     }
38     return 0;
39 }
LOJ6277

分块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
",query(l,r,c*c));
67         }
68     }
69     return 0;
70 }
分块2

(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
",query(l,r,c*c));
68         }
69     }
70     return 0;
71 }
LOJ6278

分块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
",query(l,r,c));
70         }
71     }
72     return 0;
73 }
分块3

(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
",query(l,r,c));
71         }
72     }
73     return 0;
74 }
LOJ6279

分块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
",query(l,r,c+1)%(c+1));
64         }
65     }
66     return 0;
67 }
LOJ6280

分块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
",query(l,r));
76         }
77     }    
78     return 0;
79 }
LOJ6281

分块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
",ve[t.first][t.second]);
63             }
64         }
65     }
66     return 0;
67 }
分块6

(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
",ve[t.first][t.second]);
64             }
65         }
66     }
67     return 0;
68 }
LOJ6282

分块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
",val);
66             }
67             else update(opt,l,r,c);
68         }
69     }
70     return 0;
71 }
LOJ6283

分块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
",query(l,r,c));
88             update(l,r,c);
89         }
90     }
91     return 0;
92 }
LOJ6284
原文地址:https://www.cnblogs.com/HDUjackyan/p/8878032.html