解析:只要离线一下,对于每种操作1算一下它产生贡献的区间就行了,那么这个直接线段树维护
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
int T,n,opt,l[MAXN];
long long mod,m,q[MAXN],f[MAXN<<2];
void pushdown(int k){
if (f[k]!=1)
{
f[k<<1]=(f[k<<1]*f[k])%mod; f[k<<1|1]=f[k<<1|1]*f[k]%mod; f[k]=1;
}
}
void change(int l,int r,int k,int ll,int rr,long long t)
{
if (l==ll&&r==rr)
{
f[k]=(f[k]*t)%mod;
}
else {
int mid=(l+r)/2;
pushdown(k);
if (rr<=mid) change(l,mid,k<<1,ll,rr,t); else if (ll>mid) change(mid+1,r,k<<1|1,ll,rr,t);
else {
change(l,mid,k<<1,ll,mid,t); change(mid+1,r,k<<1|1,mid+1,rr,t);
}
}
}
void pri(int l,int r,int k)
{
if (l==r) printf("%lld\n",f[k]);
else {
int mid=(l+r)/2;
pushdown(k);
pri(l,mid,k<<1); pri(mid+1,r,k<<1|1);
}
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d%lld",&n,&mod);
memset(q,0,sizeof(q));
memset(l,0,sizeof(l));
for (int i=1;i<=(n<<2);i++) f[i]=1;
for (int i=1;i<=n;i++)
{
scanf("%d%lld",&opt,&m);
if (opt==1) q[i]=m%mod; else l[m]=i-1;
}
for (int i=1;i<=n;i++)
if (q[i]){
change(1,n,1,i,l[i]?l[i]:n,q[i]);
}
pri(1,n,1);
}
}