传送门:P4588
题目描述
小豆现在有一个数 x,初始值为 1。小豆有 Q 次操作,操作有两种类型:
1 m:将 x 变为x*m,并输出x mod M
2 pos:将 x 变为 x 除以第 pos 次操作所乘的数(保证第 pos 次操作一定为类型 1,对于每一个类型 1 的操作至多会被除一次),并输出 x mod M。
输入格式
一共有 t 组输入。
对于每一组输入,第一行是两个数字 Q,M。
接下来 Q 行,每一行为操作类型 op,操作编号或所乘的数字 m(保证所有的输入都是合法的)。
输出格式
对于每一个操作,输出一行,包含操作执行后的 x mod M 的值。
输入输出样例
输入 #1
1 10 1000000000 1 2 2 1 1 2 1 10 2 3 2 4 1 6 1 7 1 12 2 7
输出 #1
2 1 2 20 10 1 6 42 504 84
说明/提示
对于 20% 的数据,1≤Q≤500。
对于 100% 的数据,1≤Q≤,t≤5,M≤
,0<m≤
。
思路
通过题目,一秒看出
线段树!
先建树:
非常简单,注意一下边界
void build(int x,int l,int r){
L[x]=l;
R[x]=r;
prod[x]=1;
if(l==r){
return;
}
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
}
接着是修改:
非常经典,不过这里需要一个新数组,prod表示区间所有数乘积。
void modify(int x,int p,int v){
if(L[x]==R[x]){
prod[x]=v;
return;
}
int mid=(L[x]+R[x])/2;
if(p<=mid){
modify(x*2,p,v);
}else{
modify(x*2+1,p,v);
}
prod[x]=1LL*prod[x*2]*prod[x*2+1]%mod;
}
主题代码就是这些,main里非常好写
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100009;
int n,mod,a[MAXN],L[MAXN*4],R[MAXN*4],prod[MAXN*4];
//prod: 区间所有数乘积
void build(int x,int l,int r){
L[x]=l;
R[x]=r;
prod[x]=1;
if(l==r){
return;
}
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
}
void modify(int x,int p,int v){
if(L[x]==R[x]){
prod[x]=v;
return;
}
int mid=(L[x]+R[x])/2;
if(p<=mid){
modify(x*2,p,v);
}else{
modify(x*2+1,p,v);
}
prod[x]=1LL*prod[x*2]*prod[x*2+1]%mod;
}
int main(){
int t;
cin>>t;
while(t--){
cin>>n>>mod;
build(1,1,n);
for(int i=1;i<=n;i++){
int q,m;
cin>>q>>m;
if(q==1){
modify(1,i,m);
cout<<prod[1]<<endl;
}else{
modify(1,m,1);
cout<<prod[1]<<endl;
}
}
}
return 0 ;
}
-----------------------------------------------------祝大家AC快乐!------------------------------------------------------