LOJ #6283. 数列分块入门 7
区间加,区间乘,单点查询。
跟线段树的差不多,为了避免精度问题要先乘再加。区别也和其他的差不多,残块暴力。然后就没什么了。scanf读int要& !
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const int mod = 10007; 7 8 int atag[350],mtag[350],v[100010],bl[100010]; 9 int n,blo,opt,l,r,c; 10 11 void down(int x){ 12 if(mtag[x]^1) 13 for(int i = (x-1)*blo+1;i <= min(n,x*blo);i++) 14 v[i] *= mtag[x],v[i] %= mod; 15 mtag[x] = 1; 16 if(atag[x]) 17 for(int i = (x-1)*blo+1;i <= min(n,x*blo);i++) 18 v[i] += atag[x],v[i] %= mod; 19 atag[x] = 0; 20 } 21 22 void add(int l,int r,int c){ 23 if(bl[l] == bl[r]){ 24 down(bl[l]); 25 for(int i = l;i <= r;i++) 26 v[i] += c,v[i] %= mod; 27 return; 28 } 29 down(bl[l]),down(bl[r]); 30 for(int i = l;i <= bl[l]*blo;i++) 31 v[i] += c,v[i] %= mod; 32 for(int i = (bl[r]-1)*blo+1;i <= r;i++) 33 v[i] += c,v[i] %= mod; 34 for(int i = bl[l]+1;i < bl[r];i++) 35 atag[i] += c,atag[i] %= mod; 36 } 37 38 int ask(int x){ 39 return (v[x]*mtag[bl[x]]%mod+atag[bl[x]])%mod; 40 } 41 42 void mul(int l,int r,int c){ 43 if(bl[l] == bl[r]){ 44 down(bl[l]); 45 for(int i = l;i <= r;i++) 46 v[i] *= c,v[i] %= mod; 47 return; 48 } 49 down(bl[l]),down(bl[r]); 50 for(int i = l;i <= bl[l]*blo;i++) 51 v[i] *= c,v[i] %= mod; 52 for(int i = (bl[r]-1)*blo+1;i <= r;i++) 53 v[i] *= c,v[i] %= mod; 54 for(int i = bl[l]+1;i < bl[r];i++) 55 atag[i] *= c,atag[i] %= mod, 56 mtag[i] *= c,mtag[i] %= mod; 57 } 58 59 int main(){ 60 scanf("%d",&n); blo = sqrt(n); 61 for(int i = 1;i <= n;i++){ 62 scanf("%d",&v[i]); 63 v[i] %= mod; 64 bl[i] = (i-1)/blo+1; 65 } 66 for(int i = 1;i <= bl[n];i++)mtag[i] = 1; 67 for(int i = 1;i <= n;i++){ 68 scanf("%d%d%d%d",&opt,&l,&r,&c); 69 switch(opt){ 70 case 0:add(l,r,c);break; 71 case 1:mul(l,r,c);break; 72 case 2:printf("%d\n",ask(r));break; 73 } 74 } 75 return 0; 76 }