【线段树】数学计算
Description
小豆现在有一个数x,初始值为1. 小豆有Q次操作,操作有两种类型: 1 m: x = x * m ,输出 x%mod; 2 pos: x = x / 第pos次操作所乘的数(保证第pos次操作一定为类型1,对于每一个类型1 的操作至多会被除一次),输出x%mod
Input
一共有t组输入(t ≤ 5) 对于每一组输入,第一行是两个数字Q, mod(Q ≤ 100000, mod ≤ 1000000000); 接下来Q行,每一行为操作类型op,操作编号或所乘的数字m(保证所有的输入都是合法的). 1 ≤ Q ≤ 100000
Output
对于每一个操作,输出一行,包含操作执行后的x%mod的值
Sample Input
1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7
Sample Output
2
1
2
20
10
1
6
42
504
84
分析
比较简单的一道线段树了 我们建立一棵线段树,其叶子节点 i ii 保存的是第 i 次操作时乘的那个值 那么对于操作二,就是单点修改为1即可
代码
#include<bits/stdc++.h> #define in read() #define lson (rt<<1) #define rson (rt<<1)|1 #define maxn 100009 #define ll long long using namespace std; int t,q,mod,m,caoz; ll dis[maxn<<2]; void build(int rt,int l,int r){ if(l==r){ dis[rt]=1; return; } int mid=l+r>>1; build(lson,l,mid);build(rson,mid+1,r); dis[rt]=dis[lson]*dis[rson]; } void insert(int rt,int l,int r,int now,ll x){ if(l==r){ dis[rt]=x%mod;return; } int mid=l+r>>1; if(now<=mid) insert(lson,l,mid,now,x); else insert(rson,mid+1,r,now,x); dis[rt]=dis[lson]*dis[rson]%mod; } void change(int rt,int l,int r,int now,int x){ if(l==r){ dis[rt]=x; return; } int mid=l+r>>1; if(now<=mid) change(lson,l,mid,now,x); else change(rson,mid+1,r,now,x); dis[rt]=dis[lson]*dis[rson]%mod; } int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&q,&mod); int rt; build(1,1,q); for(int i=1;i<=q;++i){ scanf("%d%d",&caoz,&m); if(caoz==1){ printf("%d\n",dis[1]%mod*m%mod); insert(1,1,q,i,m); } else{ change(1,1,q,m,1); printf("%d\n",dis[1]%mod); } } } return 0; }
$Never\ Give\ Up$