T1
传送门
考虑前缀和qwq
记
L
[
i
]
L[i]
L[i]表示’o’以前的‘n’数,
R
[
i
]
R[i]
R[i]表示’o’以后的’i’数
a
n
s
=
∑
i
=
l
r
[
s
[
i
]
=
o
]
(
L
[
i
]
−
L
[
l
]
)
(
R
[
i
]
−
R
[
r
]
)
=
∑
i
=
l
r
[
s
[
i
]
=
o
]
L
[
i
]
R
[
i
]
+
∑
i
=
l
r
[
s
[
i
]
=
o
]
L
[
l
]
R
[
r
]
−
L
[
l
]
∑
i
=
l
r
[
s
[
i
]
=
o
]
R
[
i
]
−
R
[
r
]
∑
i
=
l
r
[
s
[
i
]
=
o
]
L
[
i
]
\begin{aligned} ans&=\sum_{i=l}^r[s[i]=\mathrm o](L[i]-L[l])(R[i]-R[r])\\ &=\sum_{i=l}^r[s[i]=\mathrm o]L[i]R[i]+\sum_{i=l}^r[s[i]=\mathrm o]L[l]R[r]-L[l]\sum_{i=l}^r[s[i]=\mathrm o]R[i]-R[r]\sum_{i=l}^r[s[i]=\mathrm o]L[i] \end{aligned}
ans=i=l∑r[s[i]=o](L[i]−L[l])(R[i]−R[r])=i=l∑r[s[i]=o]L[i]R[i]+i=l∑r[s[i]=o]L[l]R[r]−L[l]i=l∑r[s[i]=o]R[i]−R[r]i=l∑r[s[i]=o]L[i]
不过我好像写炸了
但是对拍是对的qwq
#include<bits/stdc++.h>
using namespace std;
#define in Read()
typedef unsigned long long ull;
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
int n,m;
namespace RND{
int seed;
inline void init(){
seed=in;
srand(seed);
}
inline void getQuery(int &l,int &r){
l=(long long)rand()*rand()%n+1,r=(long long)rand()*rand()%n+1;
if(l>r)std::swap(l,r);
}
}
using RND::getQuery;
const int NNN=5e6+5;
char s[NNN];
int smn[NNN],smo[NNN],smi[NNN];
ull L[NNN],R[NNN],M[NNN];
int main(){
freopen("noi.in","r",stdin);
freopen("zxd.out","w",stdout);
n=in,m=in;
scanf("%s",s+1);
RND::init();
for(int i=1;i<=n;++i){
smn[i]=smn[i-1]+(s[i]=='n');
smo[i]=smo[i-1]+(s[i]=='o');
smi[i]=smi[i-1]+(s[i]=='i');
}
for(int i=1;i<=n;++i){
L[i]=L[i-1],R[i]=R[i-1],M[i]=M[i-1];
if(s[i]=='o'){
L[i]+=smn[i];
R[i]+=smi[n]-smi[i];
M[i]+=1ull*smn[i]*(smi[n]-smi[i]);
}
}
ull res=0,ans=0;
for(int l,r,i=1;i<=m;++i){
getQuery(l,r);
ans=0;
ans+=M[r]-M[l-1];
ans+=1ull*(smo[r]-smo[l-1])*smn[l-1]*(smi[n]-smi[r]);
ans-=(R[r]-R[l-1])*smn[l-1];
ans-=(L[r]-L[l-1])*(smi[n]-smi[r]);
res^=ans;
}
printf("%lld\n",res);
return 0;
}
T2
Tarjan
割点割边的概念
不会qwq
T3
位运算变矩阵乘
树上有树剖
区间就用数位DP
要学习一下数位DP