FZU2297 Number theory (线段树单点修改、区间查询)

题意

初始x=1,下面有Q次操作。
操作M yi:x=x*yi
操作N di:x=x/ydi
每次操作后都输出x的值。保证每次di的值都不一样。

分析

考虑暴力维护:
用一个数组y[Q+1]记录每个yi的值,初始化yi的值都为1。对于操作M yi,将第i个值改为yi。对于操作N di,将第di个值除以ydi,因为每次di的值都不一样,故除以ydi后的ydi的值为1。每次都输出y[1][y2]…*[yQ]%M即可。
时间复杂度为O(Q^2).

考虑优化:
针对一个数组的操作,即对一个区间。可以用线段树去进行维护。初始化建树,叶子节点的值为1,维护每段区间上各个元素的乘积sum。M yi,将第i个元素的值改为yi。N di,将第di个元素的值改为1。输出即查询区间[1,Q]的sum值。也就是变成了单点更新、区间查询问题。
时间复杂度为O(QlongQ)。

AC代码

#include 
#include 
#include 
#include 
#define lson p<<1
#define rson p<<1|1
typedef long long ll;
using namespace std;
const int maxn=1e5+100;
ll mod;
struct node
{
    int l,r;
    ll sum;
}T[maxn<<2];
void up(int p)
{
    T[p].sum=(T[lson].sum*T[rson].sum)%mod;
}
void build(int p,int l,int r)
{
    T[p].l=l,T[p].r=r;
    if(l==r)
    {
        T[p].sum=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    up(p);
}
void update(int p,int k,ll val)
{
    if(T[p].l==T[p].r)
    {
        T[p].sum=val;
        return ;
    }
    int mid=(T[p].l+T[p].r)>>1;
    if(k<=mid) update(lson,k,val);
    else update(rson,k,val);
    up(p);
}
int main()
{
    ios::sync_with_stdio(false);
    int kase;
    cin>>kase;
    while(kase--)
    {
        int q;
        cin>>q>>mod;
        build(1,1,q);
        for(int i=1;i<=q;i++)
        {
            char op;
            cin>>op;
            ll val;
            cin>>val;
            if(op=='M') update(1,i,val);
            else update(1,val,1);
            cout<1].sum<return 0;
}

你可能感兴趣的:(数据结构,线段树)