NC20528. [ZJOI2017]树状数组
描述
漆黑的晚上,九条可怜躺在床上辗转反侧。难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历。那是一道基础的树状数组题。给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种:
输入描述
第一行输入两个整数 n, m。
接下来 m 行每行描述一个操作,格式如题目中所示。
N ≤ 10^5,m ≤ 10^5,1 ≤ L ≤ R ≤ N
输出描述
对于每组询问,输出一个整数表示答案。
如果答案化为最简分数后形如 x/y,那么你只需要输出 x*y^?1 mod 998244353 后的值。(即输出答案模 998244353)。
示例1
输入:
5 5 1 3 3 2 3 5 2 4 5 1 1 3 2 2 5
输出:
1 0 665496236
说明:
//在进行完 Add(3) 之后, A 数组变成了 [0, 1, 1, 0, 0]。所以前两次询问可怜的程序答案都是C++(clang++ 11.0.1) 解法, 执行用时: 1320ms, 内存消耗: 206820K, 提交时间: 2022-10-25 14:09:27
#include<set> #include<map> #include<queue> #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> #define R register #define ll long long using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*f; } const int N = 1e5 + 1000,mod = 998244353; int n,T,cnt; int rt[(N << 2) + 1000]; struct node{int ls,rs,v;} tr[N * 400]; ll ksm(ll x,ll y){ll res = 1; for(;y;y >>= 1,x = x * x % mod) if(y & 1) res = res * x % mod; return res;} ll mul(ll p,ll q){ll res = p * q % mod; res = (res + (1 - p) * (1 - q) % mod) % mod; return (res + mod) % mod;} void changey(int &k,int l,int r,int x,int y,ll p) { if(!k){k = ++ cnt; tr[k].v = 1;} if(x <= l && y >= r) {tr[k].v = mul(tr[k].v,p); return;} int mid = (l + r) >> 1; if(x <= mid) changey(tr[k].ls,l,mid,x,y,p); if(y > mid) changey(tr[k].rs,mid + 1,r,x,y,p); } void changex(int k,int l,int r,int lx,int rx,int ly,int ry,ll p) { if(lx <= l && rx >= r){changey(rt[k],1,n,ly,ry,p); return ;} int mid = (l + r) >> 1; if(lx <= mid) changex(k << 1,l,mid,lx,rx,ly,ry,p); if(rx > mid) changex(k << 1 | 1,mid + 1,r,lx,rx,ly,ry,p); } ll asky(int k,int l,int r,int pos) { if(!k) return 1; if(l == r) return tr[k].v; int mid = (l + r) >> 1; if(pos <= mid) return mul(tr[k].v,asky(tr[k].ls,l,mid,pos)); else return mul(tr[k].v,asky(tr[k].rs,mid + 1,r,pos)); } ll askx(int k,int l,int r,int posx,int posy) { if(l == r) return asky(rt[k],1,n,posy); int mid = (l + r) >> 1; if(posx <= mid) return mul(askx(k << 1,l,mid,posx,posy),asky(rt[k],1,n,posy)); else return mul(askx(k << 1 | 1,mid + 1,r,posx,posy),asky(rt[k],1,n,posy)); } int main() { n = read(); T = read(); ll p; int opt,l,r; while(T --) { opt = read(); l = read(); r = read(); if(opt == 1) { p = ksm(r - l + 1,mod - 2); if(l > 1) changex(1,0,n,1,l - 1,l,r,(1 - p + mod) % mod),changex(1,0,n,0,0,1,l - 1,0); if(r < n) changex(1,0,n,l,r,r + 1,n,(1 - p + mod) % mod),changex(1,0,n,0,0,r + 1,n,0); changex(1,0,n,l,r,l,r,(1 - 2ll * p + mod) % mod); changex(1,0,n,0,0,l,r,p); } else cout << askx(1,0,n,l - 1,r) << "\n"; } return 0; }