题意:
两个操作:① 当为1时 ,乘上后面的数
② 当为2时,除以第x次乘的数
还说了2操作后面的n不会重复(就这明显看出线段树- -,然而并没有看出来,还是靠的队友)
1则对每个节点赋值,2则将相应的点改为一,每次操作后进行一次询问
#include <cstdio> #define MAXN 100010 using namespace std; long long m,ans[MAXN],q[MAXN],tree[MAXN*50]; int n; long long build(int l,int r,int rt) { if(l==r) return(tree[rt]=q[l]>1?q[l]:1); int mid=(l+r)/2; return tree[rt]=(build(l,mid,rt*2)*build(mid+1,r,rt*2+1))%m; } long long change(int l,int r,int rt,int x) { if(l==r)return tree[rt]=1; int mid=(l+r)/2; if(x<=mid)return tree[rt]=(change(l,mid,rt*2,x)*tree[rt*2+1])%m; else return tree[rt]=(tree[rt*2]*change(mid+1,r,rt*2+1,x))%m; } long long query(int l,int r,int rt,int x) { if(r==x)return tree[rt]; int mid=(l+r)/2; if(x>mid)return (tree[rt*2]*query(mid+1,r,rt*2+1,x))%m; else return query(l,mid,rt*2,x); } int main() { int T; scanf("%d",&T); for(int t=1; t<=T; ++t) { scanf("%d%lld",&n,&m); int op; ans[0]=1; for(int i=1; i<=n; i++) { ans[i]=1; scanf("%d%lld",&op,&q[i]); q[i]%=m;if(op==2)q[i]=-q[i]; } build(1,n,1); printf("Case #%d: ",t); for(int i=1; i<=n; i++) { if(q[i]>=0)ans[i]=(ans[i-1]*q[i])%m; else { change(1,n,1,-q[i]); ans[i]=query(1,n,1,i); } printf("%lld ",ans[i]); } } return 0; }