传送门: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快乐!------------------------------------------------------
文章描述了一种利用线段树数据结构解决编程题目中的数列操作问题的方法。具体操作包括构建线段树、区间乘积更新以及查询,主要应用于处理类型的1和2的操作,并给出了完整的C++实现代码。
411





