1. 程式人生 > 遊戲 >育碧荷蘭澄清Ubisoft+服務加入XGP:暫時僅登入Xbox主機

育碧荷蘭澄清Ubisoft+服務加入XGP:暫時僅登入Xbox主機

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;
}