P4588 [TJOI2018]数学计算

P4588 [TJOI2018]数学计算_第1张图片

思路分析:其实刚看到这道题的时候我想也没想直接写了一个暴力出来,没有去注意数据范围,结果1分也没得。。。看了数据范围后,我们发现会爆longlong,于是我们考虑进行优化。我们知道,操作1是将上一步得到的一个数乘另外一个数,我们就可以开一个数组,记录相应步骤时输入的值,维护总乘积,若为操作2,则将数组内相应的位置进行更新,并更新乘积,这是什么?单点修改区间查询。于是我们选用线段树进行优化。每次要求输出时输出线段树根节点的值就行了,反正问的是总乘积。

代码:

 1 #include
 2 #include
 3 #include
 4 using namespace std;
 5 const int N=5e6+10;
 6 #define int long long //偷懒写法,但可能会跑的很慢. 
 7 int n,Mod;
 8 struct Tree{
 9     int lson,rson,val;
10 }tree[N];
11 void build(int l,int r,int t){  //初始化 
12     tree[t].lson=l;tree[t].rson=r;
13     if(l==r){
14         tree[t].val=1;
15         return;
16     }
17     int mid=(l+r)>>1;
18     build(l,mid,t<<1);
19     build(mid+1,r,t<<1|1);
20     tree[t].val=tree[t<<1].val*tree[t<<1|1].val%Mod;
21 }
22 void update(int p,int l,int r,int t,int x){ //单点修改 
23     if(l==r){
24         tree[p].val=x%Mod;
25         return;
26     }
27     int mid=(l+r)>>1;
28     if(t<=mid) update(p<<1,l,mid,t,x);
29     else update(p<<1|1,mid+1,r,t,x);
30     tree[p].val=(tree[p<<1].val*tree[p<<1|1].val)%Mod;
31 }
32 signed main(){
33     //freopen("a.txt","r",stdin);
34     int T;
35     scanf("%lld",&T);
36     while(T--){
37         scanf("%lld%lld",&n,&Mod);
38         build(1,n,1);
39         for(int i=1;i<=n;++i){
40             int x,t;
41             scanf("%lld%lld",&t,&x);
42             if(t==1){  //依据情况更新 
43                 update(1,1,n,i,x);
44                 printf("%lld\n",tree[1].val);
45             }
46             else{
47                 update(1,1,n,x,1);
48                 printf("%lld\n",tree[1].val);
49             }
50         }
51     }
52     return 0;
53 }
View Code

 

你可能感兴趣的:(P4588 [TJOI2018]数学计算)