[LOJ] 分块九题 7

区间加法,区间乘法,单点查询。

洛谷线段树2
屡清加法乘法的关系,定义答案为 a*mut+add

对于整块:
新的乘w,mut和add都要乘w
新的加w,add加w

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cctype>
using namespace std;

inline int read_d(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c)) f=c=='-'?-1:1;
    while(isdigit(c)){
        ret=ret*10+c-'0';
        c=getchar();
    }
    return ret*f;
}

const int MAXN=500005;
const int MOD=10007;
int n;
int num,block;
int a[MAXN],l[MAXN],r[MAXN],bl[MAXN];
int add[MAXN],mut[MAXN];

void pushdown(int id){
    for(int i=l[id];i<=r[id];i++){
        a[i]=(a[i]*mut[id]+add[id]) % MOD;
    }
    mut[id]=1;
    add[id]=0;
}

void build(){
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1;i<=num;i++){
        l[i]=(i-1)*block+1;
        r[i]=i*block;
        mut[i]=1;
    }
    for(int i=1;i<=n;i++){
        bl[i]=(i-1)/block+1;
    }
    r[num]=n;
}

int query(int x){
    return (((a[x]*mut[bl[x]])%MOD)+add[bl[x]])%MOD;
}

void updata_mut(int x,int y,int w){
    if(bl[x]==bl[y]){
        pushdown(bl[x]);
        for(int i=x;i<=y;i++){
            a[i]*=w;
            a[i]%=MOD;
        }
        return ;
    }
    pushdown(bl[x]);
    for(int i=x;i<=r[bl[x]];i++){
        a[i]*=w;a[i]%=MOD;
    }
    pushdown(bl[y]);
    for(int i=l[bl[y]];i<=y;i++){
        a[i]*=w;a[i]%=MOD;
    }
    for(int i=bl[x]+1;i<=bl[y]-1;i++){
        mut[i]*=w;mut[i]%=MOD;
        add[i]*=w;add[i]%=MOD;
    }
}

void updata_add(int x,int y,int w){
    if(bl[x]==bl[y]){
        pushdown(bl[x]);
        for(int i=x;i<=y;i++){
            a[i]+=w;
        }
        return ;
    }
    pushdown(bl[x]);
    for(int i=x;i<=r[bl[x]];i++){
        a[i]+=w;a[i]%=MOD;
    }
    pushdown(bl[y]);
    for(int i=l[bl[y]];i<=y;i++){
        a[i]+=w;a[i]%=MOD;
    }
    for(int i=bl[x]+1;i<=bl[y]-1;i++){
        add[i]+=w;add[i]%=MOD;
    }
}

int main(){
    n=read_d();
    for(int i=1;i<=n;i++){
        a[i]=read_d();
    }
    build();
    for(int i=1;i<=n;i++){
        int q=read_d(),x=read_d(),y=read_d(),w=read_d();
        if(q==0) updata_add(x,y,w);
        if(q==1) updata_mut(x,y,w);
        if(q==2) printf("%d\n",query(y));
    }
    return 0;
}
posted @ 2018-04-13 16:46  GhostCai  阅读(114)  评论(0编辑  收藏  举报