Skip to content

11546: 【原1546】ecneuqes

题目

题目描述

author: AHOI 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1546

Description

有长为\(N\)的数列\(a_1,a_2,\cdots,a_N\), 有如下三种操作形式: 1. 把数列中的一段数全部乘一个值. 2. 把数列中的一段数全部加一个值. 3. 询问数列中的一段数的和. 由于答案可能很大,你只需输出这个数模\(P\)的值.

Input Format

第一行两个整数\(N\)和\(P\).

第二行含有\(N\)个非负整数,从左到右依次为\(a_1,a_2,\cdots,a_N \).

第三行有一个整数\(M\), 表示操作总数.

从第四行开始每行描述一个操作, 输入的操作有以下三种形式: 操作1:1 t g c.表示把所有满足\(t\leq i \leq g\)的\(a_i\)改为\(a_i\times c\). 操作2:2 t g c.表示把所有满足\(t\leq i \leq g\)的\(a_i\)改为\(a_i+ c\). 操作3:3 t g.询问所有满足\(t\leq i \leq g\)的\(a_i\)的和模\(P\)的值\(t\leq i \leq g\). 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格.

Output Format

共一行,包含一个整数表示答案。

Sample Input 1

5 19260817
976 997 1022 237 252
5
2 1 3 1000
3 3 3
1 3 5 8
3 4 5
3 1 4

Sample Output 1

2022
3912
22045

Sample Input 2

7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

Sample Output 2

2
35
8

Limits

对于\(100\%\)的数据, \(n\leq 100000, q\leq 10^9, a_i\leq 10^9\).

\(20\%\)的数据满足, \(n \leq 1000\).

\(20\%\)的数据满足只有加法操作.

\(20\%\)的数据满足: 单点修改, 区间查询.

yyong119's solution

#include <cstdio>
#include <iostream>
using namespace std;
inline const int getint() {
    int r = 0, k = 1;
    char c = getchar();
    for (; c<'0' || c>'9'; c = getchar()) if (c == ' - ') k = -1;
    for (; c >= '0'&&c <= '9'; c = getchar()) r = r * 10 + c - '0';
    return k*r;
}

const int N = 100010;
int n, MD;

struct node {
    int sum, add, mul;
    void upd(int a, int m, int len) {
        add = ((long long)add*m + a) % MD;
        mul = ((long long)mul*m) % MD;
        sum = ((long long)sum*m + (long long)a*len) % MD;
    }
}t[N << 2];

void pushdown(int x, int len) {
    if (t[x].add != 0 || t[x].mul != 1)
        t[x << 1].upd(t[x].add, t[x].mul, (len - (len >> 1))),
        t[x << 1 | 1].upd(t[x].add, t[x].mul, len >> 1),
        t[x].add = 0, t[x].mul = 1;
}

void pushup(int x) {
    t[x].sum = (t[x << 1].sum + t[x << 1 | 1].sum) % MD; 
}
void build(int l, int r, int x) {
    t[x].add = 0;
    t[x].mul = 1;
    if (l == r) { t[x].sum = getint(); return; }
    int mid = (l + r) >> 1;
    build(l, mid, x << 1); build(mid + 1, r, x << 1 | 1);
    pushup(x);
}

void update(int l, int r, int x, int L, int R, int add, int mul) {
    if (L <= l && r <= R) { t[x].upd(add, mul, r - l + 1); return; }
    pushdown(x, r - l + 1);
    int mid = (l + r) >> 1;
    if (L <= mid) update(l, mid, x << 1, L, R, add, mul);
    if (mid<R) update(mid + 1, r, x << 1 | 1, L, R, add, mul);
    pushup(x);
}

int query(int l, int r, int x, int L, int R) {
    if (L <= l && r <= R) return t[x].sum;
    pushdown(x, r - l + 1);
    int mid = (l + r) >> 1, ret = 0;
    if (L <= mid) ret += query(l, mid, x << 1, L, R);
    if (mid<R) ret += query(mid + 1, r, x << 1 | 1, L, R);
    ret %= MD;
    return ret;
}

int main() {
    scanf("%d%d", &n, &MD);
    build(1, n, 1);
    int m;
    scanf("%d", &m);
    while (m--) {
        int c;
        scanf("%d", &c);
        int l, r, x;
        switch (c) {
            case 1:
                scanf("%d%d%d", &l, &r, &x);
                update(1, n, 1, l, r, 0, x);
                break;
            case 2:
                scanf("%d%d%d", &l, &r, &x);
                update(1, n, 1, l, r, x, 1);
                break;
            case 3:
                scanf("%d%d", &l, &r);
                printf("%d\n", query(1, n, 1, l, r));
                break;
        }
    }
    return 0;
}