线段树求调
查看原帖
线段树求调
546558
Land_ER楼主2021/12/11 08:00
#include<cstdio>
#include<cstring>
#define ll_ long long
#define re_ register
#define maxn_ 100005
#define child ((id<<1)+1)
#define mid (((r-l)>>1)+l)
ll_ int a[maxn_],d[maxn_<<4],tag1[maxn_<<4],tag2[maxn_<<4];//1*2+
ll_ int n,m,p;
ll_ int read(void){
    ll_ int r = 0,w = 1;
    re_ char c;
    c = getchar();
    if(c == '-'){
        w = -1;
        c = getchar();
    }
    while(c>='0' && c<='9'){
        r = r*10 + c-'0';
        c = getchar();
    }
    return r*w;
}
void input(void){
    n = read();
    m = read();
    p = read();
    for(re_ int i = 1;i <= n;++ i)
        a[i] = read();
    for(re_ int i = 0;i < maxn_<<4;++ i)
        tag1[i] = 1;
    return;
}
void build(int id,int l,int r){
    if(l == r)
        d[id] = a[l] % p;
    else{
        build(child,l,mid);
        build(child+1,mid+1,r);
        d[id] = (d[child] + d[child+1]) % p;
    }
    return;
}
void pushdown(int id,int l,int r){
    d[child] = (d[child]*tag1[id]%p + tag2[id]*(mid-l+1)%p) % p;
    d[child+1] = (d[child+1]*tag1[id]%p + tag2[id]*(r-mid)%p) % p;
    tag1[child] *= tag1[id];
    tag1[child+1] *= tag1[id];
    tag2[child] *= tag1[id];
    tag2[child+1] *= tag1[id];
    tag2[child] += tag2[id];
    tag2[child+1] += tag2[id];
    tag1[id] = 1;
    tag2[id] = 0;
    return;
}
void update(int id,int l,int r,int s,int e,int add,int mul){
    #ifdef debug
    printf("%d %d %d %d %d %d %d\n",id,l,r,s,e,add,mul);
    Sleep(1000);
    #endif
    if(s<=l && e>=r){
        d[id] = d[id]*mul + (r-l+1)*add;
        tag1[id] *= mul;
        tag2[id] *= mul;
        tag2[id] += add;
    }
    else{
        if(s <= mid)
            update(child,l,mid,s,e,add,mul);
        if(e > mid)
            update(child+1,mid+1,r,s,e,add,mul);
        d[id] = (d[child]+d[child+1])%p;
    }
    return;
}
ll_ int getsum(int id,int l,int r,int s,int e){
    if(s<=l && e>=r)
        return d[id];
    else{
        ll_ int ret = 0;
        pushdown(id,l,r);
        if(s <= mid)
            ret += getsum(child,l,mid,s,e)%p;
        if(e > mid)
            ret += getsum(child+1,mid+1,r,s,e)%p;
        return ret%p;
    }
}
void solve(void){
    ll_ int op,x,y,k;
    for(re_ int i = 0;i < m;++ i){
        op = read();
        x = read();
        y = read();
        if(op == 1){
            k = read();
            update(0,1,n,x,y,0,k);
        }
        else if(op == 2){
            k = read();
            update(0,1,n,x,y,k,1);
        }
        else
            printf("%lld\n",getsum(0,1,n,x,y));
    }
    return;
}
int main(void){
    input();
    build(0,1,n);
    solve();
    return 0;
}
2021/12/11 08:00
加载中...