POJ5475 An easy problem【单点更新】

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5475


题目大意:

有一个特殊的计算器,初始值 X = 1。现在有两种操作:

1. 乘以 Y

2. 除以一个之前乘过的数。

每次操作之后,输出对 M 取余的值。


解题思路:

操作有 10^5 个,可以看作是有 10^5 个数字,他们的初始值都为1.

每次操作对其中一个数字进行修改:

1. 把第 i 个数字改成 y

2. 把地 y 个数字改成 1,当作之前没有乘过。

用线段树 sum[] 来计算乘积,然后每次输出 sum[1]。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL __int64
using namespace std;
const int MAXN = 100010;
LL sum[MAXN<<2],Mod;

void Pushup(int root)
{
    sum[root] = sum[root<<1] * sum[root<<1|1] % Mod;
}

void Build(int root,int L,int R)
{
    sum[root] = 1;
    if(L == R)
        return ;
    int mid = (L+R)>>1;
    Build(root<<1,L,mid);
    Build(root<<1|1,mid+1,R);
    Pushup(root);
}

void Update(int root,int L,int R,int s,LL e)
{
    if(L == R)
    {
        sum[root] = e % Mod;
        return;
    }
    int mid = (L+R)>>1;
    if(s <= mid)
        Update(root<<1,L,mid,s,e);
    else
        Update(root<<1|1,mid+1,R,s,e);
    Pushup(root);
}

int main()
{
    int T,kase = 0,N,op;
    LL d;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%I64d",&N,&Mod);
        Build(1,1,N);
        printf("Case #%d:\n",++kase);
        for(int i = 1; i <= N; ++i)
        {
            scanf("%d%I64d",&op,&d);
            if(op == 1)
                Update(1,1,N,i,d);
            else
                Update(1,1,N,d,1);
            printf("%I64d\n",sum[1]);
        }
    }

    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/u011676797/article/details/49077785