Zoj 4009 Segment Tree

The meaning of the question: Given the modulus 99971, two operations are maintained on the interval, one is the tripartite of all the numbers in the interval, and the other is the interval summation. (both are operations in the sense of modulo)

practice: take note 3 48 1 mod 99970 , then by Fermat's little theorem, we have a 3 48 a mod 99971 . So for any number, doing 48 tripartite operations will inevitably cycle, of course, some numbers may not need 48 cycles, but it is obvious that all cycle lengths are factors of 48.
Build a line segment tree, each node records the shift of the sum of all numbers on the line segment corresponding to the current node, 0 times, 1 time... until the value of 47 times, and also maintains a lazy mark, indicating the number of shifts in the entire segment. Note that pushup and pushdown should correspond to the order of sum.

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long ll;
const int maxn=100005;
const int mod=99971;
inline ll p3(ll x){
    return (x*x%mod)*x%mod;
}
ll a[maxn][48];
int n,q;
ll sum[maxn<<2][48];
ll lz[maxn<<2];
ll tmp[48];
void pushup(int u){
    for(int i=0;i<48;i++){
        sum[u][i]=sum[2*u][(i+lz[2*u])%48]+sum[2*u+1][(i+lz[2*u+1])%48];
    }
}
void pushdown(int u){
    lz[2*u]=(lz[2*u]+lz[u])%48;
    lz[2*u+1]=(lz[2*u+1]+lz[u])%48;
    for(int i=0;i<48;i++)tmp[i]=sum[u][(i+lz[u])%48];
    memcpy(sum[u],tmp,sizeof(tmp));
    lz[u]=0;
}
void build(int u,int l,int r){
    lz[u]=0;
    if(l==r){
        for(int i=0;i<48;i++)sum[u][i]=a[l][i];
        return;
    }
    int mid=(l+r)/2;
    build(2*u,l,mid);
    build(2*u+1,mid+1,r);
    pushup(u);
}
void update(int u,int l,int r,int ql,int qr){
    if(ql>r||qr<l)return;
    if(ql<=l&&r<=qr){
        lz[u]=(lz[u]+1)%48;
        return;
    }
    int mid=(l+r)/2;
    if(lz[u])pushdown(u);
    update(2*u,l,mid,ql,qr);
    update(2*u+1,mid+1,r,ql,qr);
    pushup(u);
}
ll query(int u,int l,int r,int ql,int qr){
    if(ql>r||qr<l)return 0;
    if(ql<=l&&r<=qr){
        return sum[u][lz[u]];
    }
    int mid=(l+r)/2;
    if(lz[u])pushdown(u);
    return (query(2*u,l,mid,ql,qr)+query(2*u+1,mid+1,r,ql,qr))%mod;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i][0]);
            for(int j=1;j<48;j++){
                a[i][j]=p3(a[i][j-1]);
            }
        }
        build(1,1,n);
        for(int i=1;i<=q;i++){
            int tag,l,r;
            scanf("%d%d%d",&tag,&l,&r);
            if(tag==1)update(1,1,n,l,r);
            else printf("%lld\n",query(1,1,n,l,r));
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325945891&siteId=291194637