【循环节+线段树】ZOJ4009 And Another Data Structure Problem

S o u r c e : Source: Source:151 - ZOJ Monthly, March 2018
P r o b l e m : Problem: Problem:

  • 1 l r: Change $(a_l, a_{l+1}, \dots, a_r) $to $(a_l^3, a_{l+1}^3, \dots, a_r^3)$;
  • 2 l r: Query the value of $(\displaystyle\sum_{i=l}^r a_i)$ modulo 99971.
$Idea:$ 注意到所有数的操作的循环节都是48。用线段树维护每个区间的整个循环节。

C o d e : Code: Code:

#include<bits/stdc++.h>
using namespace std;

#define lson o<<1
#define rson o<<1|1
const int MOD = 99971;
const int MAXN = 1e5+10;

struct Node {
    int add, sum[50], t[50];
}b[MAXN<<2];

int ql, qr, a[MAXN], mark[50];

int sqr3(int x) { return 1LL*x*x%MOD*x%MOD; }

void build(int o, int L, int R) {
    b[o].add = 0;
    if(L == R) {
        b[o].sum[0] = a[L];
        b[o].t[0] = b[o].sum[0];
        for(int i = 1; i < 48; i++) {
            b[o].sum[i] = sqr3(b[o].sum[i-1]);
            b[o].t[i] = b[o].sum[i];
        }
        return;
    }
    int M = (L+R)>>1;
    build(lson, L, M);
    build(rson, M+1, R);
    for(int i = 0; i < 48; i++) {
        b[o].sum[i] = (b[lson].sum[i]+b[rson].sum[i])%MOD;
    }
}

void maintain(int o, int L, int R) {
    for(int i = 0; i < 48; i++) {
        if(R > L) b[o].sum[i] = (b[lson].sum[i]+b[rson].sum[i])%MOD;
        else b[o].sum[i] = b[o].t[i];
    }
    int now = b[o].add;
    now %= 48;
    if(now) {
        for(int i = 0; i < 48; i++) mark[i] = b[o].sum[i];
        for(int i = 0; i < 48; i++) b[o].sum[i] = mark[(i+now)%48];
    }
}

void pushdown(int o) {
    b[lson].add += b[o].add;
    b[rson].add += b[o].add;
    b[o].add = 0;
}

void update(int o, int L, int R) {
    if(ql<=L && qr>=R) {
        b[o].add++;
    }
    else {
        pushdown(o);
        int M = (L+R)>>1;
        if(ql <= M) update(lson, L, M); else maintain(lson, L, M);
        if(qr > M) update(rson, M+1, R); else maintain(rson, M+1, R);
    }
    maintain(o, L, R);
}

int query(int o, int L, int R, int add) {
    if(ql<=L && qr>=R) return b[o].sum[add%48];
    else {
        int M = (L+R)>>1;
        int ret = 0;
        if(ql <= M) ret += query(lson, L, M, add+b[o].add);
        if(qr > M) ret += query(rson, M+1, R, add+b[o].add);
        return ret%MOD;
    }
}

int main() {
    int X;
    scanf("%d", &X);
    while(X--) {
        int n, q;
        scanf("%d%d", &n, &q);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            a[i] %= MOD;
        }
        build(1, 1, n);
        while(q--) {
            int op;
            scanf("%d%d%d", &op, &ql, &qr);
            if(op == 1) update(1, 1, n);
            else printf("%d\n", query(1, 1, n, 0));
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值