P4588 [TJOI2018]数学计算

P4588 [TJOI2018]数学计算

分析

太有意思哇,巧妙的很哇。

初一看这个题,觉得这么简单?

然后发现直接模拟肯定不行啊,直接模拟G了,因为mod的数不是个质数,也没办法很好的直接算。

看了题解,太妙了。

解法

我们按照时间轴建树。初始时每个叶节点都赋1,最后维护区间乘的结果。

对于两个操作

  • x*m,则我们在第i个位置插入m
  • x/第pos个操作的数,则将pos位置置为1

则直接查tr[1]即为答案,巧妙啊。

直接看看代码。

Ac_code

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct Node
{
    int l,r,sum;
}tr[N<<2];
int n,m;

void pushup(int u)
{
    tr[u].sum = 1ll*tr[u<<1].sum*tr[u<<1|1].sum%m;
}

void build(int u,int l,int r)
{
    if(l==r)
    {
        tr[u] = {l,r,1};
        return ;
    }
    tr[u] = {l,r};
    int mid = l + r >> 1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    pushup(u);
}

void modify(int u,int x,int k)
{
    if(tr[u].l==tr[u].r)
    {
        tr[u].sum = k;
        return ;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if(x<=mid) modify(u<<1,x,k);
    else modify(u<<1|1,x,k);
    pushup(u);
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=n;i++)
        {
            int op,t;scanf("%d%d",&op,&t);
            if(op==1) modify(1,i,t);
            else modify(1,t,1);
            printf("%d\n",tr[1].sum);
        }
    }
    return 0;
}
posted @ 2022-05-05 21:14  艾特玖  阅读(32)  评论(0)    收藏  举报