牛客oj小Cの棋王の道(暴力ブロック+ブロック再構築)

45985 ワード

転送ドアのWAは12発も通っていない.主に区間賦値の操作が複雑になったと思う.出会った問題を分かち合う.問題を考慮して与えたいくつかの操作:1.区間プラス区間でこの2つに乗るのは難しくないので、乗るときにブロックの中の加算マークも乗せればいいです.2区間賦値これは、実は上の2つの操作で導き出すことができ、1つのマークを追加して記録しないでください(速度が遅く、コードの難易度が高くなります).0に乗ってxを加えればOKです.3 xを末尾に追加する.この操作は、最後のブロックのサイズを大きくする可能性がある.この操作がsqrt(n)を超えるときにブロックを再構成することができる.この回数は一度にO(n)である.しかもsqrt(n)回を超えることはない.複雑度の面ではブロックがsqrt(n)をとると全体的にO(nsqrt(n))である.テーマは3 sです.だからかろうじて足りる.型取り演算を減らすことに注意する.2つのintmaxを掛けるとlonglongmaxは爆発しません.だから真ん中に型を取らなくてもいいです.コード#コード#
#pragma GCC optimize(2)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector
#define sd second
#define ALL(a) a.begin(),a.end()
#include 
  
using namespace std;
const int N = 2e5+10;
  
inline LL read(){
    LL x = 0,f=1;char ch = getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,blo,num,mod,pos[N];
LL L[N],R[N],sum[N],add[N],mul[N],a[N];
void clr(int i){
    fir(j,L[i],R[i]) a[j] = (a[j]*mul[i]+ add[i])%mod;
    sum[i] = (sum[i]*mul[i]+(R[i]-L[i]+1)*add[i])%mod;
    add[i] = 0;mul[i] = 1;
}
bool f = 0;
void build(){
    if(f){
        fir(i,1,num){
            clr(i);
        }
    }
    blo = sqrt(n);
    num = n/blo;
    fir(i,1,num){
        L[i] = (i-1)*blo+1;
        R[i] = i*blo;
    }
    if(n % blo){
        num++;
        L[num] = R[num-1]+1;
        R[num] = n;
    }
    if(!f){
        f = 1;
        fir(i,1,N-1) add[i] = 0,sum[i] = 0,mul[i] = 1;
        fir(i,1,num){
            sum[i] = 0;add[i] = 0;mul[i] = 1;
            fir(j,L[i],R[i]){
                sum[i] = (sum[i] + a[j])%mod;
                pos[j] = i;
            }
        }
        return;
    }
    fir(i,1,num){
        sum[i] = 0;add[i] = 0;mul[i] = 1;
        fir(j,L[i],R[i]){
            sum[i] = (sum[i] + a[j])%mod;
            pos[j] = i;
        }
    }
}
void Add(int l,int r,LL v){
    int p = pos[l],q = pos[r];
    if(p == q){
        clr(p);
        fir(i,l,r) a[i] = (a[i] + v)%mod,sum[p] = (sum[p]+v)%mod;
    }
    else{
        fir(i,p+1,q-1){
            add[i] = (add[i] + v)%mod;
        }
        clr(p);
        fir(i,l,R[p]) a[i] = (a[i] + v)%mod;
        sum[p] = (sum[p] + (R[p]-l+1)*v)%mod;
        clr(q);
        fir(i,L[q],r) a[i] = (a[i] + v)%mod;
        sum[q] = (sum[q] + (r-L[q]+1)*v)%mod;
    }
}
void Mul(int l,int r,LL v){
    int p = pos[l],q = pos[r];
    if(p == q){
        clr(p);
        fir(i,l,r){
            sum[p] = (sum[p]-a[i]+mod)%mod;
            a[i] = a[i]*v%mod;
            sum[p] = (sum[p]+a[i])%mod;
        }
    }
    else{
        fir(i,p+1,q-1){
            mul[i] = (mul[i]*v)%mod,add[i] = add[i]*v%mod;
        }
        clr(p);
        fir(i,l,R[p]){
            sum[p] = (sum[p]-a[i]+mod)%mod;
            a[i] = a[i]*v%mod;
            sum[p] = (sum[p]+a[i])%mod;
        }
        clr(q);
        fir(i,L[q],r){
            sum[q] = (sum[q]-a[i]+mod)%mod;
            a[i] = a[i]*v%mod;
            sum[q] = (sum[q]+a[i])%mod;
        }
    }
}
LL query(int l,int r){
    int p = pos[l],q = pos[r];
    LL res = 0;
    if(p == q){
        clr(p);
        fir(i,l,r){
            res = (res + a[i])%mod;
        }
    }
    else{
        fir(i,p+1,q-1){;
            res = (res + sum[i]*mul[i] + (R[i]-L[i]+1)*add[i])%mod;
        }
        clr(p);
        fir(i,l,R[p]){
            res = (res + a[i])%mod;
        }
        clr(q);
        fir(i,L[q],r){
            res = (res + a[i])%mod;
        }
    }
    return res;
}
int main(){
    n = read(); m = read(); mod = read();
    fir(i,1,n) a[i] = read();
    build();
    int cnt = 0;
    while(m--){
        int op,l,r,x;
        cin >> op;
        if(op <= 3){
            l = read(); r =read(); x= read();
            if(op == 1) Add(l,r,x);
            else if(op == 2) Mul(l,r,x);
            else{
            	Mul(l,r,0);
            	Add(l,r,x);
            }
        }
        else if(op == 4){
            cnt++;
            x = read();
            a[++n] = x;
            clr(num);
            R[num]++;
            sum[num] = (sum[num]+x)%mod;
            pos[n] = num;
            if(cnt > blo){
                build();
                cnt = 0;
            }
        }
        else{
            l = read(); r = read();
            printf("%lld
"
,query(l,r)); } } return 0; }