Description
小豆现在有一个数 x,初始值为1。小豆有Q次操作,操作有两种类型:
1 m:x=x×m ,输出 x mod M ;
2 pos:x=x/ 第 pos 次操作所乘的数(保证第 pos 次操作一定为类型1,对于每一个类型1的操作至多会被除一次),输出 x mod M 。
Input
一共有t组输入。
对于每一组输入,第一行是两个数字Q,M 。
接下来 Q 行,每一行为操作类型op,操作编号或所乘的数字m(保证所有的输入都是合法的)。
Output
对于每一个操作,输出一行,包含操作执行后的x mod M的值
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
Hint
对于 20% 的数据, 1≤Q≤500
对于 100% 的数据, 1≤Q≤10^5,t≤5,M≤10^9
线段树分治裸题,我认为唯一一个坑点是我只把操作1当成了操作。。。
另外,这道题不开longlong会炸。
#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,R) for(register int i=(L);i<=(R);++i)
#define Red(j,R,L) for(register int j=(R);j>=(L);--j)
#define int long long
const int N = 1e5+10;
int n,p;
struct SegMent{
struct Tree{
int L,r,mul;
}t[N<<2];
#define Ls v<<1
#define rs v<<1|1
inline void build(int v,int L,int r){
t[v]=(Tree){L,r,1};
if(L==r)return ;
int Mid=L+r>>1;
build(Ls,L,Mid),build(rs,Mid+1,r);
}
inline void update(int v,int A,int b,int k){
if(t[v].L>b||t[v].r<A)return ;
if(A<=t[v].L&&t[v].r<=b)return t[v].mul=1ll*t[v].mul*k%p,void();
update(Ls,A,b,k),update(rs,A,b,k);
}
inline void Query(int v,int k){
k=1ll*k*t[v].mul%p;
if(t[v].L==t[v].r)return cout<<k<<"\n",void();
Query(Ls,k),Query(rs,k);
}
}t;
struct Operator{
int pos,m;
}a[N];
inline void init(){
scanf("%lld%lld",&n,&p);
t.build(1,1,n);
Inc(i,1,n){
int op,x;scanf("%lld%lld",&op,&x);
if(op==1)a[i]=(Operator){i,x};
else {
t.update(1,a[x].pos,i-1,a[x].m);
a[x]=(Operator){0,0};
}
}
Inc(i,1,n)if(a[i].pos)t.update(1,a[i].pos,n,a[i].m);
Inc(i,1,n)a[i]=(Operator){0,0};
}
signed main(){
int T;scanf("%lld",&T);
while(T--){
init();
t.Query(1,1);
}
return 0;
}