【学习】分块

题目及思路来自 hzwer.com

题目来自LOJ数列分块入门by hzw

持续咕咕咕中~

 

 

数列分块入门1

区间加,单点查询

code

 1 void add(int a,int b,int c){
 2     for(int i=a;i<=min(b,blo[a]*block);i++){
 3         v[i]+=c;
 4     }
 5     if(blo[a]!=blo[b]){
 6         for(int i=(blo[b]-1)*block+1;i<=b;i++){
 7             v[i]+=c;
 8         }
 9     }
10     for(int i=blo[a]+1;i<=blo[b]-1;i++){
11         tg[i]+=c;
12     }
13 }
区间加
1 if(f==1)printf("%d\n",v[b]+tg[blo[b]]);
单点查询

 

数列分块入门2

区间加,查询区间内小于x的元素个数

块内set维护

code

 1 int query(int a,int b,int c)
 2 {
 3     int ans=0;
 4     for(int i=a;i<=min(bl[a]*blo,b);i++)
 5         if(v[i]+atag[bl[a]]<c)ans++;
 6     if(bl[a]!=bl[b])
 7         for(int i=(bl[b]-1)*blo+1;i<=b;i++)
 8             if(v[i]+atag[bl[b]]<c)ans++;
 9     for(int i=bl[a]+1;i<=bl[b]-1;i++)
10     {
11         int x=c-atag[i];
12         ans+=lower_bound(ve[i].begin(),ve[i].end(),x)-ve[i].begin();
13     }
14     return ans;
15 }
查询元素个数

 

数列分块入门4

区间加,区间求和

先预处理区间和后再同上

code

 1 void add(int l,int r,int c){
 2     for(int i=l;i<=min(r,bl[l]*block);i++){
 3         sum[bl[l]]+=c;v[i]+=c;
 4     }
 5     if(bl[l]!=bl[r]){
 6         for(int i=(bl[r]-1)*block+1;i<=r;i++){
 7             sum[bl[r]]+=c;v[i]+=c;
 8         }
 9     }
10     for(int i=bl[l]+1;i<=bl[r]-1;i++){
11         tg[i]+=c;
12     }
13 }
预处理区间和&&区间加
 1 ll query(int l,int r){
 2     int ans=0;
 3     for(int i=l;i<=min(r,bl[l]*block);i++){
 4         ans+=v[i]+tg[bl[l]];
 5     }
 6     if(bl[l]!=bl[r]){
 7         for(int i=(bl[r]-1)*block+1;i<=r;i++){
 8             ans+=v[i]+tg[bl[r]];
 9         }
10     }
11     for(int i=bl[l]+1;i<=bl[r]-1;i++){
12         ans+=sum[i]+block*tg[i];
13     }
14     return ans;
15 }
16 
17 
18 
19 if(op==1)printf("%lld\n",query(l,r)%(c+1));
查询区间和

 

数列分块入门7

区间乘,区间加

维护multi-tag和add-tag同时乘法的优先级高于加法

code

 1 void solve(int f,int l,int r,int c){
 2     reset(bl[l]);
 3     for(int i=l;i<=min(bl[l]*blo,r);i++){
 4         if(f==0)v[i]+=c;
 5         else v[i]*=c;
 6         v[i]%=mod;
 7     }
 8     if(bl[l]!=bl[r]){
 9         reset(bl[r]);
10         for(int i=(bl[r]-1)*blo+1;i<=r;i++){
11             if(f==0)v[i]+=c;
12             else v[i]*=c;
13             v[i]%=mod;
14         }
15     }
16     for(int i=bl[l]+1;i<=bl[r]-1;i++){
17         if(f==0)atg[i]=(atg[i]+c)%mod;
18         else {
19             atg[i]=(atg[i]*c)%mod;
20             mtg[i]=(mtg[i]*c)%mod;
21         }
22     }
23 }
区间加&&区间乘
1 void reset(int x){
2     for(int i=(x-1)*blo+1;i<=min(n,x*blo);i++){
3         v[i]=(v[i]*mtg[x]+atg[x])%mod;
4     }
5     atg[x]=0;mtg[x]=1;
6 }
更新

 

 

posted @ 2019-10-16 19:21  喵の耳  阅读(187)  评论(0编辑  收藏  举报