zoukankan      html  css  js  c++  java
  • 洛谷P4588 [TJOI2018]数学计算

    解题报告

    发现这个过程用操作序列描述起来比较清晰

    比如一溜乘法操作

    1 2
    1 2
    1 4
    1 6
    2 3
    

    前四个操作就可以描述成

    x = 1
    | *2
    x = 2
    | *4
    x = 8
    | *6
    x = 48
    

    而除法操作就是把对应操作序号删掉,换句话说,把乘数改成 1

    x = 1
    | *2
    x = 2
    | *1
    x = 2
    | *6
    x = 12
    

    接下来把操作序列横着画

    1 1 1 1 1 1 1 ... x = 1
    2 4 6 1 1 1 1 ... x = 2 * 4 * 6 = 48
    2 1 6 1 1 1 1 ... x = 2 * 1 * 6 = 12
    

    发现这不就是个前缀积吗!

    于是题目转化成了:

    给定一个全为 1 的序列,每次修改一个数,求前缀积。

    线段树一波搞定。

    代码实现

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <string>
    #include <vector>
    
    #define forall(G,i) for (int i = 0, __for_siz__ = (int) (G).size(); i < __for_siz__; ++i) 
    #define DEBUG(x) std::cerr << #x << " = " << x << std::endl;
    #define ALL(x) (x).begin(), (x).end()
    #define MP std::make_pair
    #define se second
    #define fi first
    
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read() {
        int s = 0, x = 1; char ch = getchar();
        while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); }
        while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); }
        return s * x;
    }
    
    int Q, M;
    
    struct SegmentTree {
        static const int MAXQ = 100000 + 10;
    
    #define ls ((p) << 1)
    #define rs ((p) << 1 | 1)
    
        int mul[MAXQ << 2];
    
        SegmentTree() {}
        
        void Update(int p) {
            mul[p] = (long long int) mul[ls] * (long long int) mul[rs] % M;
        }
    
        void buildTree(int p, int l, int r) {
            if (l == r) {
                mul[p] = 1; return;
            } int mid = (l + r) >> 1;
            buildTree(ls, l, mid); buildTree(rs, mid + 1, r);
            Update(p);
        }
    
        void Modify(int p, int l, int r, int pos, int k) {
            if (l == r) {
                mul[p] = k % M; return;
            } int mid = (l + r) >> 1;
            if (pos <= mid) Modify(ls, l, mid, pos, k);
            else Modify(rs, mid + 1, r, pos, k);
            Update(p);
        }
    
        int Query(int p, int l, int r, int ll, int rr) {
            if (l == ll && rr == r) return mul[p];
            int mid = (l + r) >> 1;
            if (rr <= mid) return Query(ls, l, mid, ll, rr);
            else if (mid + 1 <= ll) return Query(rs, mid + 1, r, ll, rr);
            else return (long long int) Query(ls, l, mid, ll, mid) 
                        * (long long int) Query(rs, mid + 1, r, mid + 1, rr) % M;
        }
    } segt;
    
    int T;
    
    int main() {
        T = read();
        while (T --> 0) {
            Q = read(); M = read();
            segt.buildTree(1, 1, Q);
            for (int i = 1; i <= Q; ++i) {
                int op = read(); int m = read();
                if (op == 1) segt.Modify(1, 1, Q, i, m);
                else segt.Modify(1, 1, Q, m, 1);
                printf("%d
    ", segt.Query(1, 1, Q, 1, Q));
    
                // for (int i = 1; i <= 20; ++i) printf("%d%c", segt.mul[i], i == 20 ? '
    ' : ' ');
            }
        }
        return 0;
    }
    
  • 相关阅读:
    HTML5学习笔记-2.HTML基础
    HTML5学习笔记-1.网页入门
    Java学习笔记-8.多线程编程
    Java学习笔记-7.Java IO流
    Java学习笔记-6.Java异常处理
    Java学习笔记-5.常用数据结构
    Java学习笔记-4.继承与多态
    Java学习笔记-3.类与对象
    C语言学习笔记-10.文件
    .net core 中threadpool用法
  • 原文地址:https://www.cnblogs.com/handwer/p/14681644.html
Copyright © 2011-2022 走看看