给定一个长度为 且只由
,
,
三种小写英文字母组成的字符串
,现在有
次操作。
每次操作都有两种可能:
给定一个整数 ,表示在
后插入一个
字符(插入字符后的下标依次顺延)。
给定两个整数 ,查询
这个字符串区间中为
的子序列的数量。
如果一个字符串 能通过删除一些元素(可以不删也可以删完)得到字符串
,那么字符串
就是字符串
的子序列。
第一行输入两个整数
表示字符串长度和询问次数。
为了减少输入量,你需要用备注中给出的随机数生成器来生成字符串
和
次操作。
第二行将输入三个范围在 unsigned int 内的整数
用于生成数据,具体生成代码将在备注中给出。
在执行给出生成代码的 gen() 函数后,字符串
将保存在名为 _s 的全局 char 类型的数组中,满足任意
。
次操作的操作类型将会保存在名为 _opt 的全局 int 类型的数组中,对于第
次操作:
如果 _opt[i] 的值为,那么操作中的整数
将保存在名为 _l[i] 的全局 int 类型的数组中。
如果 _opt[i] 的值为,那么操作中的整数
将分别保存在名为 _l[i] 和 _r[i] 的全局 int 类型的数组中。
我们如下定义
:
如果第次操作为
号操作,那么
。
如果第次操作为
号操作,那么
即该次询问的答案。
为了减少输出量,你只需要输出所有
的异或和即可。
unsigned int SA,SB,SC;
unsigned int rnd()
{
SA^=SA<<16;
SA^=SA>>5;
SA^=SA<<1;
unsigned int t=SA;
SA=SB;SB=SC;
SC^=t^SA;
return SC;
}
int n,q;
char _s[1000005];
int _opt[1000005];
int _l[1000005],_r[1000005];
void gen()
{
scanf("%d%d",&n,&q);
scanf("%u%u%u",&SA,&SB,&SC);
for(int i=1;i<=n;i++)
{
int si=rnd()%3;
if(si==0) _s[i]='o';
if(si==1) _s[i]='r';
if(si==2) _s[i]='z';
}
for(int i=1;i<=q;++i)
{
_opt[i]=rnd()%2+1;
if(_opt[i]==1)
_l[i]=rnd()%n+1;
else
{
int l=rnd()%n+1;
int r=rnd()%n+1;
if(l>r) std::swap(l,r);
_l[i]=l;_r[i]=r;
}
}
}