P4588 [TJOI2018]数学计算 题解
题意简述
初值为 ,要求支持以下操作:
操作 1:将 ,输出 ;
操作 2:将 , 是第 次操作时乘上的数,输出 。
分析
线段树好题!线段树好题!线段树好题!
做过这道题后,我真的对线段树有了更加深厚的了解。
看到这个题目其实很难想象可以使用线段树来做,但我们可以发现,如果我们按照时间轴,即 建一棵线段树,第 个数即为 ,一开始全部赋初值 。
第 个操作为 1 时就单点修改 ,这样 push_up
时就可以将 。
为 2 时可以单点修改 ,这样 push_up
时, 就相当于除以了 (第 次操作乘上的数)。
每次查询,输出 tr[1].sum
即可。
这样一分析,就变成了线段树裸题了(甚至还简单,都不用区间查询)。
代码实现
#include <bits/stdc++.h> #define int long long using namespace std; inline int read(){ int x=0,f=0;char ch=getchar(); while(!isdigit(ch))f^=!(ch^45),ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; } inline void write(int x){ if(x<0)x=-x,putchar('-'); if(x>=10)write(x/10); putchar(x%10+'0'); } inline void writeln(int x){write(x);puts("");} int T,Q,mod; struct segment{ int l,r,sum; }tr[100005<<2]; inline int ls(int p){return p<<1;} inline int rs(int p){return p<<1|1;} inline void push_up(int p){tr[p].sum=(tr[ls(p)].sum*tr[rs(p)].sum)%mod;} void build(int p,int l,int r){ tr[p]={l,r,1}; if(l==r)return; int mid=l+r>>1; build(ls(p),l,mid); build(rs(p),mid+1,r); push_up(p); } void update(int p,int x,int k){ if(tr[p].l==tr[p].r){ tr[p].sum=k; return; } int mid=tr[p].l+tr[p].r>>1; if(x<=mid)update(ls(p),x,k); if(mid<x)update(rs(p),x,k); push_up(p); } signed main(){ T=read(); while(T--){ Q=read();mod=read(); memset(tr,0,sizeof tr); build(1,1,Q); for(int i=1;i<=Q;i++){ int p=read(),m=read(); if(p==1)update(1,i,m),writeln(tr[1].sum%mod); else update(1,m,1),writeln(tr[1].sum%mod); } } #ifndef ONLINE_JUDGE system("pause"); #endif return 0; }
本文作者:tmjyh09
本文链接:https://www.cnblogs.com/tmjyh09/p/15916280.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步