被俘虏
a-d省略
e 线段树
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+6;
namespace modnum_space {
typedef long long ll;
const ll pmod = 998244353;
struct modnum;
modnum inv(modnum a);
ll exgcd(ll a, ll b, ll &x, ll &y);
modnum qpow(modnum a, modnum b, modnum p);
struct modnum {
ll val;
modnum(){ val = 0; }
modnum(ll a) { val = (a%pmod+pmod)%pmod; }
modnum(int a) { val = (a%pmod+pmod)%pmod; }
friend modnum operator + (const modnum &a, const modnum &b){ return (a.val+b.val)%pmod; }
friend modnum operator - (const modnum &a, const modnum &b){ return (a.val-b.val+pmod)%pmod; }
friend modnum operator * (const modnum &a, const modnum &b){ return (a.val*b.val)%pmod; }
friend modnum operator / (const modnum &a, const modnum &b){ return (a.val*inv(b.val)).val%pmod; }
friend modnum& operator += (modnum &a, const modnum &b){ return a = a+b; }
friend modnum& operator -= (modnum &a, const modnum &b){ return a = a-b; }
friend modnum& operator *= (modnum &a, const modnum &b){ return a = a*b; }
friend modnum& operator /= (modnum &a, const modnum &b){ return a = a/b; }
};
modnum inv(modnum a)
{
ll x, y;
exgcd(a.val, pmod, x, y);
x = (x%pmod+pmod)%pmod;
return x;
}
modnum qpow(modnum a, ll b)
{
modnum ans = 1;
for(; b; b >>= 1, a *= a)
if(b&1) ans *= a;
return ans;
}
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if(b == 0){ return x = 1, y = 0, a; }
ll d = exgcd(b, a%b, x, y);
ll z = x; x = y; y = z-(a/b)*y;
return d;
}
#ifdef _GLIBCXX_IOSTREAM
std::istream& operator >> (std::istream& cin, modnum &a)
{ cin >> a.val; a.val %= pmod; return cin; }
std::ostream& operator << (std::ostream& cout, modnum a)
{ cout << a.val; return cout; }
#endif
}
using namespace modnum_space;
#define z modnum
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
int a[N];
int mod=1e9;
long long gcd(long long x, long long y) {
return y ? gcd(y, x % y) : x;
}
int n;
string s;
struct node
{ int l,r;
z w;
ll w0,w1;//数量
ll x0,x1;//
}tr[N << 2];
struct sb{
node hb(node a,node b){
int mid=a.r;
node c;
c.w=a.w+b.w;
c.w1=a.w1+b.w1;
c.w0=a.w0+b.w0;
c.x0=a.x0+b.x0;
c.x1=a.x1+b.x1;
c.w+=(mid*a.w1-a.x1)*b.w0
+(mid*a.w0-a.x0)*b.w1
+(b.x1-mid*b.w1)*a.w0
+(b.x0-mid*b.w0)*a.w1;
c.r=b.r;
c.l=a.l;
return c;
}
void push_up(int i){
int mid=tr[ls(i)].r;
tr[i].w=tr[ls(i)].w+tr[rs(i)].w;
tr[i].w1=tr[ls(i)].w1+tr[rs(i)].w1;
tr[i].w0=tr[ls(i)].w0+tr[rs(i)].w0;
tr[i].x0=tr[ls(i)].x0+tr[rs(i)].x0;
tr[i].x1=tr[ls(i)].x1+tr[rs(i)].x1;
tr[i].w+=(mid*tr[ls(i)].w1-tr[ls(i)].x1)*tr[rs(i)].w0
+(mid*tr[ls(i)].w0-tr[ls(i)].x0)*tr[rs(i)].w1
+(tr[rs(i)].x1-mid*tr[rs(i)].w1)*tr[ls(i)].w0
+(tr[rs(i)].x0-mid*tr[rs(i)].w0)*tr[ls(i)].w1;
}
void build (int l,int r,int i){
tr[i].l=l;
tr[i].r=r;
if(l==r){
tr[i].w=0;
tr[i].w1+= a[l]==1? 1:0;
tr[i].w0+= a[l]==0? 1:0;
tr[i].x0+=a[l]==0? l:0;
tr[i].x1+=a[l]==1? l:0;
return;
}
int mid=l+r>>1;
build(l,mid,ls(i));
build(mid+1,r,rs(i));
push_up(i);
}
node query1(int ql,int qr,int l,int r,int i){
if(ql<=l&&r<=qr){
return tr[i];
}
node ans;
int mid=l+r>>1;
//cout<<l<<' '<<' '<<r<<'\n';
if(ql<=mid&&qr>mid){
node a=query1(ql,qr,l,mid,ls(i));
node b=query1(ql, qr, mid + 1, r, rs(i));
ans=hb(a,b);
}
else if(ql<=mid){
node a=query1(ql,qr,l,mid,ls(i));
ans=a;
}
else{
node b=query1(ql, qr, mid + 1, r, rs(i));
ans=b;
}
return ans;
}
}s1;
int q;
void solve() {
cin>>n>>q;
cin>>s;
for(int i=0;i<n;i++){
a[i+1]=s[i]-'0';
}
s1.build(1,n,1);
while(q--){
int l,r;
cin>>l>>r;
node ans=s1.query1(l,r,1,n,1);
cout<<ans.w<<'\n';
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--){
solve();
}
return 0;
}