1. 程式人生 > >Loj 6283. 數列分塊入門 7

Loj 6283. 數列分塊入門 7

color ++ 運算 std sqrt sca clas define oid

鏈接:https://loj.ac/problem/6283

思路:

多重標記下放,之前寫過線段樹的多重標記,兩個思路是一樣的,都是優先處理乘法操作,如果當前塊出現乘法操作,那麽加法標記也要乘上乘法標記,這樣運算的時候就可以直接乘上乘法標記加上加法標記

如果當前塊出現加法操作,那只對加法標記有影響,加上去就好了

實現代碼;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 1e5+10;
int mtag[M],atag[M],a[M],bl[M],n,block;
const int mod = 10007; void resert(int x){ for(int i = (x-1)*block+1;i <= min(x*block,n);i ++) a[i] = (a[i]*mtag[x] + atag[x])%mod; atag[x] = 0; mtag[x] = 1; } void update(int f,int l,int r,int c){ resert(bl[l]); for(int i = l;i <= min(bl[l]*block,r);i ++){
if(f == 1) a[i] = (a[i]*c)%mod; else a[i] = (a[i]+c)%mod; } if(bl[l] != bl[r]){ resert(bl[r]); for(int i = (bl[r]-1)*block+1;i <= r;i ++){ if(f == 1) a[i] = (a[i]*c)%mod; else a[i] = (a[i] + c)%mod; } } for(int
i = bl[l]+1;i <= bl[r]-1;i ++){ if(f == 1) { atag[i] = (atag[i]*c)%mod; mtag[i] = (mtag[i]*c)%mod; } else atag[i] = (atag[i]+c)%mod; } } int main() { int f,l,r,c; scanf("%d",&n); block = sqrt(n); for(int i = 1;i <= n;i ++) scanf("%d",&a[i]); for(int i = 1;i <= n;i ++) bl[i] = (i-1)/block + 1; for(int i = 1;i <= bl[n];i ++) mtag[i] = 1,atag[i] = 0; for(int i = 1;i <= n;i ++){ scanf("%d%d%d%d",&f,&l,&r,&c); if(f == 2) printf("%d\n",(a[r]*mtag[bl[r]] + atag[bl[r]])%mod); else update(f,l,r,c); } return 0; }

Loj 6283. 數列分塊入門 7