线段树
因为模数不一定是质数,所以不能用逆元做
那么就用线段树维护一下每个位置要乘的数(2操作或已经除掉的位置就是1)
另外注意下线段树加数时记得先模一下模数,不然会爆longlong
/**************************************************************
Problem: 5334
User: syh0313
Language: C++
Result: Accepted
Time:5560 ms
Memory:7544 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using
namespace
std;
const
int
maxn=100010;
int
T,n,topt,root,l;
long
long
mo,r;
struct
da{
int
lc,rc;
long
long
sum;}a[maxn*4];
void
init()
{
for
(
int
i=0;i<=topt;i++) a[i].lc=a[i].rc=0,a[i].sum=1ll;
topt=0;
}
inline
void
updata(
int
n){a[n].sum=a[lch].sum*a[rch].sum%mo;}
void
build_tree(
int
&n,
int
l,
int
r)
{
n=++topt; a[n].sum=1ll;
if
(l==r)
return
;
int
mid=(l+r)>>1;
build_tree(lch,l,mid); build_tree(rch,mid+1,r);
updata(n);
}
void
tree_add(
int
n,
int
l,
int
r,
int
lc,
long
long
k)
{
if
(l==r) {a[n].sum=k;
return
;}
int
mid=(l+r)>>1;
if
(lc<=mid) tree_add(lch,l,mid,lc,k);
else
tree_add(rch,mid+1,r,lc,k);
updata(n);
}
long
long
qury(
int
n,
int
L,
int
R,
int
l,
int
r)
{
if
(L==l && R==r)
return
a[n].sum;
int
mid=(L+R)>>1;
if
(r<=mid)
return
qury(lch,L,mid,l,r);
else
if
(l>=mid+1)
return
qury(rch,mid+1,R,l,r);
else
return
qury(lch,L,mid,l,mid)*qury(rch,mid+1,R,mid+1,r)%mo;
}
int
main()
{
scanf
(
"%d"
,&T);
while
(T--)
{
init();
scanf
(
"%d%lld"
,&n,&mo); build_tree(root,1,n);
for
(
int
i=1;i<=n;i++)
{
scanf
(
"%d%lld"
,&l,&r);
if
(l==1) tree_add(root,1,n,i,r%mo);
else
tree_add(root,1,n,r,1);
printf
(
"%lld\n"
,qury(root,1,n,1,i));
}
}
return
0;
}