当前位置: 代码迷 >> 综合 >> FZU2297 Number theory (线段树单点修改、区间查询)
  详细解决方案

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

热度:73   发布时间:2023-11-22 00:28:43.0

题意

初始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 <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#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<<T[1].sum<<endl;}}return 0;
}
  相关解决方案