码迷,mamicode.com
首页 > 其他好文 > 详细

TJOI2018 数学计算

时间:2020-05-27 20:46:10      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:数字   span   线段树   math   执行   ==   --   bit   ace   

题目

小豆现在有一个数 \(x\) ,初始值为 \(1\) 。 小豆有 \(Q\) 次操作,操作有两种类型:

  1. \(m\)\(x=x×m\),输出 \(x\mod M\)

  2. \(pos\)\(x=x/\)\(pos\) 次操作所乘的数(保证第 \(pos\) 次操作一定为类型 \(1\),对于每一个类型 \(1\) 的操作至多会被除一次),输出 \(x\mod M\)

输入格式

一共有 \(t\) 组输入。
对于每一组输入,第一行是两个数字 \(Q,M\)
接下来 \(Q\) 行,每一行为操作类型 \(op\) ,操作编号或所乘的数字 \(m\) (保证所有的输入都是合法的)。

输出格式

对于每一个操作,输出一行,包含操作执行后的 \(x\mod M\)的值

样例输入

1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7

样例输出

2
1
2
20
10
1
6
42
504
84

数据范围

对于 \(20\%\) 的数据, \(1≤Q≤500\)
对于 \(100\%\) 的数据, \(1≤Q≤10^5,t≤5,M≤10^9\)

题解

使用线段树存储区间积, 每次除改回来一个点

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 10;
int n, p;
struct Tree {
    struct Data { int L, r, mul; } data[N << 2];
    void build(int v, int L, int r) {
        data[v] = (Data){L, r, 1};
        if (L == r) return;
        int mid = L + r >> 1;
        build(v << 1, L, mid), build(v << 1 | 1, mid + 1, r);
    }
    void update(int v, int A, int b, int k) {
        if (data[v].L > b || data[v].r < A) return;
        if (A <= data[v].L && data[v].r <= b)
            return data[v].mul = 1ll * data[v].mul * k % p, void();
        update(v << 1, A, b, k), update(v << 1 | 1, A, b, k);
    }
    void query(int v, int k) {
        k = 1ll * k * data[v].mul % p;
        if (data[v].L == data[v].r) return printf("%d\n", k), void();
        query(v << 1, k), query(v << 1 | 1, k);
    }
} tree;
struct OP { int pos, m; } a[N];
signed main() {
    int T;
    scanf("%lld", &T);
    while (T--) {
        scanf("%lld%lld", &n, &p);
        tree.build(1, 1, n);
        for (int i = 1; i <= n; i++) {
            int op, x;
            scanf("%lld%lld", &op, &x);
            if (op == 1) a[i] = (OP){i, x};
            else {
                tree.update(1, a[x].pos, i - 1, a[x].m);
                a[x] = (OP){0, 0};
            }
        }
        for (int i = 1; i <= n; i++)
            if (a[i].pos) tree.update(1, a[i].pos, n, a[i].m);
        for (int i = 1; i <= n; i++) a[i] = (OP){0, 0};
        tree.query(1, 1);
    }
    return 0;
}

TJOI2018 数学计算

标签:数字   span   线段树   math   执行   ==   --   bit   ace   

原文地址:https://www.cnblogs.com/youxam/p/tjoi2018.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!