zoukankan      html  css  js  c++  java
  • 专题训练之分块

    推荐博客: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
  • 相关阅读:
    Eclipse中web项目部署至Tomcat步骤
    解释Eclipse下Tomcat项目部署路径问题(.metadata.pluginsorg.eclipse.wst.server.core mp0wtpwebapps)
    JAVA_HOME环境变量失效的解决办法
    java 程序运行过程 简介
    深入研究Java类加载机制
    SPRING SECURITY JAVA配置:Web Security
    Spring mvc Security安全配置
    FastDateFormat
    Hibernate中Criteria的完整用法
    升级win10,提示(RAM)内存不足2G的解决的方法,亲測可行
  • 原文地址:https://www.cnblogs.com/HDUjackyan/p/8878032.html
Copyright © 2011-2022 走看看