Link
Solve
这道题初看没什么想法,然后想到每次去除一个以前出现过的数也许就等于撤销操作,然后每次只改动一个数,线段树就可以很好的完成这个效果,然后就是一个水题了,代码实现起来也不难
拿时间为线建一颗线段树,然后每次修改第(i)号位置上的值,最后求和的时候取树根就好了
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=100005;
LL c[maxn<<2],Mod,Q,lst[maxn];
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
void pushup(int x){
c[x]=c[x<<1]*c[x<<1|1]%Mod;
}
void Build(int x,int L,int R){
if(L==R){c[x]=1;return;}
int mid=(R-L>>1)+L;
Build(x<<1,L,mid);Build(x<<1|1,mid+1,R);
pushup(x);
return ;
}
void change(int x,int L,int R,int pos,LL val){
if(L==R){c[x]=val;return;}
int mid=(R-L>>1)+L;
if(pos<=mid)change(x<<1,L,mid,pos,val);
else change(x<<1|1,mid+1,R,pos,val);
pushup(x);
return ;
}
int main(){
freopen("P4588.in","r",stdin);
freopen("P4588.out","w",stdout);
int P=read();
while(P--){
Q=read(),Mod=read();
Build(1,1,Q);
for(int i=1;i<=Q;i++){
int T=read();
if(T==1){
LL v=lst[i]=read();
change(1,1,Q,i,v);
}
else{
LL v=read();
change(1,1,Q,v,1);
}
printf("%d
",c[1]);
}
}
return 0;
}