数学计算 LibreOJ - 2573 线段树

题目描述

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

1 m: x=x×m ,输出 xmodM ;

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

Input

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

Output

对于每一个操作,输出一行,包含操作执行后的 xmodM 的值

Example

样例输入

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

Hint

对于 20% 的数据, 1≤Q≤500 ;
对于 100% 的数据, 1≤Q≤105,t≤5,M≤109 。

分析

这道题最简单的做法应该就是线段树了
对于第i次操作
如果是操作1,我们将编号为i的节点乘m,维护一个单点修改,最后输出区间乘积
如果是操作2,我们把编号为i的节点的权值改为1可以了,因为每一个节点只会修改一次,同样是输出区间乘积

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll m,mod,q;
struct tre{
    ll l,r,val;
}tr[maxn<<2];
void push_up(ll da){
    tr[da].val=(tr[da<<1].val%mod*tr[da<<1|1].val%mod);
}
void build(ll da,ll le,ll ri){
    tr[da].l=le;
    tr[da].r=ri;
    if(le==ri){
        tr[da].val=1;
        return;
    }
    ll mids=(le+ri)>>1;
    build(da<<1,le,mids);
    build(da<<1|1,mids+1,ri);
    push_up(da);
}
void gai(ll da,ll bh,ll w){
    if(tr[da].l==tr[da].r){
        tr[da].val=w%mod;
        return;
    }
    ll mids=(tr[da].l+tr[da].r)>>1;
    if(bh<=mids) gai(da<<1,bh,w);
    else gai(da<<1|1,bh,w);
    push_up(da);
}
void gai2(ll da,ll bh,ll w){
    if(tr[da].l==tr[da].r){
        tr[da].val=tr[da].val%mod*w%mod;
        return;
    }
    ll mids=(tr[da].l+tr[da].r)>>1;
    if(bh<=mids) gai(da<<1,bh,w);
    else gai(da<<1|1,bh,w);
    push_up(da);
}
ll qh(ll da,ll le,ll ri){
    if(le<=tr[da].l && ri>=tr[da].r){
        return tr[da].val%mod;
    }
    ll ans=1;
    ll mids=(tr[da].l+tr[da].r)>>1;
    if(le<=mids) ans=ans*qh(da<<1,le,ri)%mod;
    if(ri>mids) ans=ans*qh(da<<1|1,le,ri)%mod;
    return ans%mod;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%lld%lld",&q,&mod);
        build(1,1,q);
        for(ll i=1;i<=q;i++){
            ll t;
            scanf("%lld%lld",&t,&m);
            if(t==1){
                gai2(1,i,m);
                printf("%lld\n",qh(1,1,i)%mod);
            } else {
                gai(1,m,1);
                printf("%lld\n",qh(1,1,i)%mod);
            }
        }
    }
    return 0;
}

posted @ 2020-05-26 09:50  liuchanglc  阅读(161)  评论(0编辑  收藏  举报