这是一道神题。
结论题。
考场上我居然只打了暴搜,连dp都没敲。
省选debuff挺高的啊其实是因为我是蒟蒻智商不够
这题是非常可做的。
考完订正时,借着题解推了推,很快——
当询问的l>1时,是问l-1~r-1与l~r的答案是否一样。
当l==1时,是询问到点r的前缀和是否等于后缀和。
无脑树套树啊。
我的常数丑了uoj上额外数据T了,97分;bzoj上约19.5s过了。
Code:
/**************************************************************
Problem: 4785
User: chenyanbo
Language: C++
Result: Accepted
Time:19572 ms
Memory:354452 kb
****************************************************************/
#include
#include
#include
#include
#include
#define N 100010
using namespace std;
const int MO=998244353;
inline int read()
{
int ret=0; char c=getchar();
while(c>57 || c<48)c=getchar();
while(c<=57 && c>=48)ret=ret*10+c-48,c=getchar();
return ret;
}
struct Tree
{
int Son[2];
int Val;
}T[300*N];
int Root[4*N];
int n,m,Cnt;
int ret;
inline int Power(int x, int k)
{
int s=1;
while(k)
{
if(k&1)s=(long long)s*x%MO;
x=(long long)x*x%MO;
k/=2;
}
return s;
}
inline int Merge(int p1, int p2)
{
return ((long long)p1*p2+(long long)(1-p1+MO)*(1-p2+MO))%MO;
}
inline int NewNode()
{
++Cnt;
T[Cnt].Son[0]=T[Cnt].Son[1]=0;
T[Cnt].Val=1;
return Cnt;
}
void Modify2(int &v, int l, int r, int x, int y, int mul)
{
if(!v)v=NewNode();
if(l==x&&r==y)
{
T[v].Val=Merge(T[v].Val,mul);
return;
}
int mid=(l+r)>>1;
if (y<=mid)Modify2(T[v].Son[0],l,mid,x,y,mul);
else if(x>mid)Modify2(T[v].Son[1],mid+1,r,x,y,mul);
else
{
Modify2(T[v].Son[0],l,mid,x,mid,mul);
Modify2(T[v].Son[1],mid+1,r,mid+1,y,mul);
}
}
void Modify1(int v, int l, int r, int x1, int y1, int x2, int y2, int val)
{
if(l==x1&&r==y1)
{
Modify2(Root[v],0,n+1,x2,y2,val);
return;
}
int mid=(l+r)>>1;
if (y1<=mid)Modify1(v<<1,l,mid,x1,y1,x2,y2,val);
else if(x1>mid)Modify1((v<<1)+1,mid+1,r,x1,y1,x2,y2,val);
else
{
Modify1(v<<1,l,mid,x1,mid,x2,y2,val);
Modify1((v<<1)+1,mid+1,r,mid+1,y1,x2,y2,val);
}
}
void Search2(int v, int l, int r, int x)
{
if(!v)return;
ret=Merge(ret,T[v].Val);
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)Search2(T[v].Son[0],l,mid,x);
else Search2(T[v].Son[1],mid+1,r,x);
}
void Search1(int v, int l, int r, int x, int y)
{
if(Root[v])Search2(Root[v],0,n+1,y);
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)Search1(v<<1,l,mid,x,y);
else Search1((v<<1)+1,mid+1,r,x,y);
}
int main()
{
n=read(),m=read();
for(int i=1; i<=m ; ++i)
{
int op,l,r;
op=read(),l=read(),r=read();
if (op==1)
{
int p=Power(r-l+1,MO-2);
if (l>1)Modify1(1,0,n,1,l-1,l,r,(1-p+MO)%MO);
if (r
Modify1(1,0,n,l,r,l,r,(1-p+MO)%MO);
Modify1(1,0,n,0,0,0,l-1,0);
Modify1(1,0,n,0,0,r+1,n+1,0);
Modify1(1,0,n,0,0,l,r,Power(r-l+1,MO-2)%MO);
}
else
{
ret=1;
Search1(1,0,n,l-1,r);
printf("%d\n",ret);
}
}
}