再次怀疑自己的智商
这个东西 不难发现求成了后缀和
当
l>1
时就是询问
al−1=ar
的概率
当
l=1
特判下
然后就是一个修改会对几个矩阵范围内的询问点造成影响
具体就是两个概率
p
和
然后这个东西 分治啊 树套树啊 都行吧
我懒就随手打了个KDTREE 竟然跑过了
rank倒数第二 竟然没有垫底
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int P=998244353;
const int N=100005;
ll inv[N];
inline void Pre(int n){
inv[1]=1; for (int i=2;i<=n;i++) inv[i]=(ll)(P-P/i)*inv[P%i]%P;
}
int n,m;
int z[N],x[N],y[N];
inline ll mul(ll p,ll q){
return (p*(1+P-q)+q*(1+P-p))%P;
}
namespace SEG{
ll T[N<<2];
inline void Build(int x,int l,int r){
T[x]=0; int mid=(l+r)>>1;
if (l==r) return;
Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
}
int ql,qr; ll t;
inline void modify(int x,int l,int r){
if (ql<=l && r<=qr){
T[x]=mul(t,T[x]); return;
}
if (T[x]) T[x<<1]=mul(T[x],T[x<<1]),T[x<<1|1]=mul(T[x],T[x<<1|1]),T[x]=0;
int mid=(l+r)>>1;
if (ql<=mid) modify(x<<1,l,mid);
if (qr>mid) modify(x<<1|1,mid+1,r);
}
inline void Modify(int _l,int _r,ll _t){
ql=_l; qr=_r; t=_t;
modify(1,1,n);
}
inline ll Query(int x,int l,int r,int t){
if (l==r) return T[x];
if (T[x]) T[x<<1]=mul(T[x],T[x<<1]),T[x<<1|1]=mul(T[x],T[x<<1|1]),T[x]=0;
int mid=(l+r)>>1;
if (t<=mid) return Query(x<<1,l,mid,t);
else return Query(x<<1|1,mid+1,r,t);
}
}
namespace KD{
int D;
int x1,x2,y1,y2; ll t;
struct PP{
int ls,rs; ll T,F;
int x[2],minv[2],maxv[2];
PP() {}
PP(int _x,int _y){ x[0]=_x; x[1]=_y; }
bool operator < (const PP &B) const{
return x[D]==B.x[D]?x[D^1]<B.x[D^1]:x[D]<B.x[D];
}
bool inside(){
return x1<=x[0] && x[0]<=x2 && y1<=x[1] && x[1]<=y2;
}
bool in(){
return x1<=minv[0] && maxv[0]<=x2 && y1<=minv[1] && maxv[1]<=y2;
}
bool out(){
return maxv[0]<x1 || minv[0]>x2 || maxv[1]<y1 || minv[1]>y2;
}
}p[N];
int tot,rt;
#define LS p[x].ls
#define RS p[x].rs
inline void upd(int x){
for (int i=0;i<2;i++){
p[x].minv[i]=p[x].maxv[i]=p[x].x[i];
if (LS) {
p[x].minv[i]=min(p[x].minv[i],p[LS].minv[i]);
p[x].maxv[i]=max(p[x].maxv[i],p[LS].maxv[i]);
}
if (RS) {
p[x].minv[i]=min(p[x].minv[i],p[RS].minv[i]);
p[x].maxv[i]=max(p[x].maxv[i],p[RS].maxv[i]);
}
}
}
inline void push(int x){
if (p[x].F){
if (LS) p[LS].F=mul(p[x].F,p[LS].F),p[LS].T=mul(p[x].F,p[LS].T);
if (RS) p[RS].F=mul(p[x].F,p[RS].F),p[RS].T=mul(p[x].F,p[RS].T);
p[x].F=0;
}
}
inline void Build(int &x,int l,int r,int d){
if (l>r){ x=0; return; }
D=d; int mid=(l+r)>>1;
nth_element(p+l,p+mid,p+r+1);
x=mid; p[x].F=p[x].T=0;
Build(p[mid].ls,l,mid-1,d^1);
Build(p[mid].rs,mid+1,r,d^1);
upd(mid);
}
inline void modify(int x){
if (p[x].in()) { p[x].F=mul(t,p[x].F); p[x].T=mul(t,p[x].T); return; }
if (p[x].out()) return;
if (p[x].inside()) p[x].T=mul(t,p[x].T);
push(x);
if (LS) modify(LS);
if (RS) modify(RS);
}
inline void Modify(int _x1,int _x2,int _y1,int _y2,ll _t){
x1=_x1; x2=_x2; y1=_y1; y2=_y2; t=_t;
modify(rt);
}
inline ll query(int x,int _x,int _y,int d){
if (p[x].x[0]==_x && p[x].x[1]==_y)
return p[x].T;
push(x);
D=d;
if (PP(_x,_y)<p[x]) return query(LS,_x,_y,d^1);
else return query(RS,_x,_y,d^1);
}
inline ll Query(int x,int y){
return query(rt,x,y,0);
}
}
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m); Pre(n);
for (int i=1;i<=m;i++){
using namespace KD;
read(z[i]); read(x[i]); read(y[i]);
if (z[i]==2){
x[i]--;
if (!x[i]) z[i]++;
if (z[i]==2) p[++tot].x[0]=x[i],p[tot].x[1]=y[i];
}
}
SEG::Build(1,1,n);
KD::Build(KD::rt,1,KD::tot,0);
int sum=0;
for (int i=1;i<=m;i++)
if (z[i]==1){
sum^=1; int l=x[i],r=y[i];
SEG::Modify(l,r,inv[r-l+1]);
if (l-1>=1) KD::Modify(1,l-1,l,r,inv[r-l+1]);
if (r+1<=n) KD::Modify(l,r,r+1,n,inv[r-l+1]);
KD::Modify(l,r,l,r,2*inv[r-l+1]%P);
}else if (z[i]==2){
ll t=KD::Query(x[i],y[i]);
printf("%lld\n",(1+P-t)%P);
}else{
ll t=SEG::Query(1,1,n,y[i]);
printf("%lld\n",!sum?(1+P-t)%P:t);
}
return 0;
}