洛谷 P4588 [TJOI2018]数学计算 (线段树)

-
题意:RT,但是这题不能直接模拟(因为会炸longlong?).
-
题解:我们可以用线段树来处理,如果是操作1,就找到叶子结点将它修改为\(m\),如果是操作\(2\),我们就将修改位置的叶子结点修改为\(1\)即可,这样的话整个操作中就没有除法出现,也应该不会炸long long,每次询问根节点的值即可.
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n,m; ll a[N]; struct misaka{ int l,r; ll val; }tr[N<<2]; void push_up(int u){ tr[u].val=(tr[u<<1].val*tr[u<<1|1].val)%m; } void build(int u,int l,int r){ if(l==r) tr[u]={l,r,1}; else{ tr[u]={l,r,0}; int mid=(l+r)>>1; build(u<<1,l,mid),build(u<<1|1,mid+1,r); push_up(u); } } void update(int u,int pos,int v){ if(tr[u].l==tr[u].r) tr[u].val=v; else{ int mid=(tr[u].l+tr[u].r)>>1; if(pos<=mid) update(u<<1,pos,v); else update(u<<1|1,pos,v); push_up(u); } } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int _; cin>>_; while(_--){ cin>>n>>m; build(1,1,n); rep(i,1,n){ int op,v; cin>>op>>v; if(op==1){ update(1,i,v); cout<<tr[1].val<<'\n'; } else{ update(1,v,1); cout<<tr[1].val<<'\n'; } } } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮

浙公网安备 33010602011771号