[TJOI2018]数学计算

题目链接

维护除法的取余需要逆元,显然这题数据量不支持这么做
考虑维护一个数据结构,除法改为:x变成1
这样所有数字的乘积就是现在的答案
线段树维护区间乘积+单点修改即可

#include <iostream>
using namespace std;
#define MAXN 100005

int Q,M;

struct Segment_Tree {
    long long seg[MAXN<<2];
    #define lson (rt<<1)
    #define rson (rt<<1|1)

    inline void pushup(int rt) {
        seg[rt] = seg[lson] * seg[rson] % M;
    }
    void Build(int rt,int l,int r) {
        if(l==r) {
            seg[rt] = 1;
            return;
        }
        int mid = (l+r) >> 1;
        Build(lson,l,mid);
        Build(rson,mid+1,r);
        pushup(rt);
    }
    void update(long long C,int L,int rt,int l,int r) {
        if(l==r) {
            seg[rt] = C;
            return;
        }
        int mid = (l+r) >> 1;
        if(L<=mid) update(C,L,lson,l,mid); 
        if(L>mid) update(C,L,rson,mid+1,r);
        pushup(rt);
    }
    long long query(int L,int R,int rt,int l,int r) {
        if(L>r||R<l) return 1;
        if(L<=l&&R>=r) return seg[rt];
        int mid = (l+r) >> 1; long long ans = 1;
        if(L<=mid) ans = ans*query(L,R,lson,l,mid)%M; 
        if(R>mid) ans = ans*query(L,R,rson,mid+1,r)%M;
        pushup(rt);
        return ans;
    }
} tr;

int main() {

	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	int T; cin >> T;
	while(T--) {

		cin >> Q >> M;
		tr.Build(1,1,Q);

		for(int i=1;i<=Q;++i) {
			int op; long long x;
			cin >> op >> x;
			if(op==1) {
				tr.update(x,i,1,1,Q);
				cout << tr.query(1,Q,1,1,Q) << '\n';
			}
			else {
				tr.update(1,x,1,1,Q);
				cout << tr.query(1,Q,1,1,Q) << '\n'; 
			} 
		}
	}

	return 0;
}
posted @ 2021-10-27 23:42  Neworld1111  阅读(27)  评论(0编辑  收藏  举报