Description
pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是333 的倍数。他想研究对于二进
制,是否也有类似的性质。于是他生成了一个长为n 的二进制串,希望你对于这个二进制串的一个子区间,能求出
其有多少位置不同的连续子串,满足在重新排列后(可包含前导0 )是一个3 的倍数。两个位置不同的子区间指开
始位置不同或结束位置不同。由于他想尝试尽量多的情况,他有时会修改串中的一个位置,并且会进行多次询问。
Input
输入第一行包含一个正整数n ,表示二进制数的长度。
之后一行n 个空格隔开的整数,保证均是0 或1 ,表示该二进制串。
之后一行一个整数m ,表示询问和修改的总次数。
之后m 行每行为1 i,表示pupil 修改了串的第i个位置(0 变成1 或1 变成0 ),或2 l r
表示pupil 询问的子区间是[l,r] 。
串的下标从1 开始。
1≤n,m≤100000
Output
对于每次询问,输出一行一个整数表示对应该询问的结果。
Sample Input
4
1 0 1 0
3
2 1 3
1 3
2 3 4
Sample Output
2
3
说明
样例解释
对于第一个询问,区间[2,2] 只有数字0 ,是3 的倍数,区间[1,3]
可以重排成011(2)=3(10),是3 的倍数,其他区间均不能重排成3 的倍数。
对于第二个询问,全部三个区间均能重排成3 的倍数(注意00 也是合法的)。
解题思路:
考虑用总数减去不合法区间数。
可以得到结论,不能组成3的倍数的就只有2种情况。
1.只有1个1的区间;
2.有奇数个1且少于2个0的区间。
我们可以用两颗线段树分别维护动态规划计算这两种区间的个数,但发现两种都包含了1,10,01三种区间,所以再用两个树状数组维护以上三种区间个数加回去即可
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=100005;
int n,m,a[N];
struct BIT
{
int a[N];
inline void add(int i,int x){for(;i<=n;i+=i&-i)a[i]+=x;}
inline int query(int i){int res=0;for(;i;i-=i&-i)res+=a[i];return res;}
inline int Query(int l,int r){return query(r)-query(l-1);}
}bit1,bit2;
struct Segtree1
{
ll f[N<<2][4][2][2];
inline void update(int p,int p1,int p2)
{
for(int i=0;i<=1;i++)for(int k=0;k<=1;k++)
{
f[p][0][i][k]=f[p1][0][i][k]+f[p2][0][i][k]+f[p1][2][i][k]+f[p2][1][i][k];
f[p][1][i][k]=f[p1][3][i][k]+f[p1][1][i][k];
f[p][2][i][k]=f[p2][3][i][k]+f[p2][2][i][k];
f[p][3][i][k]=0;
}
for(int i=0;i<=1;i++)for(int j=0;i+j<=1;j++)
{
f[p][0][0][i+j]+=f[p1][2][0][i]*f[p2][1][0][j]+f[p1][2][1][i]*f[p2][1][1][j];
f[p][0][1][i+j]+=f[p1][2][0][i]*f[p2][1][1][j]+f[p1][2][1][i]*f[p2][1][0][j];
f[p][1][0][i+j]+=f[p1][3][0][i]*f[p2][1][0][j]+f[p1][3][1][i]*f[p2][1][1][j];
f[p][1][1][i+j]+=f[p1][3][0][i]*f[p2][1][1][j]+f[p1][3][1][i]*f[p2][1][0][j];
f[p][2][0][i+j]+=f[p1][2][0][i]*f[p2][3][0][j]+f[p1][2][1][i]*f[p2][3][1][j];
f[p][2][1][i+j]+=f[p1][2][0][i]*f[p2][3][1][j]+f[p1][2][1][i]*f[p2][3][0][j];
f[p][3][0][i+j]+=f[p1][3][0][i]*f[p2][3][0][j]+f[p1][3][1][i]*f[p2][3][1][j];
f[p][3][1][i+j]+=f[p1][3][0][i]*f[p2][3][1][j]+f[p1][3][1][i]*f[p2][3][0][j];
}
}
inline void build(int p,int l,int r)
{
if(l==r){a[l]?f[p][3][1][0]=1:f[p][3][0][1]=1;return;}
int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
update(p,p<<1,p<<1|1);
}
inline void modify(int p,int l,int r,int pos)
{
if(l==r)
{
if(a[l])f[p][3][1][0]=1,f[p][3][0][1]=0;
else f[p][3][0][1]=1,f[p][3][1][0]=0;
return;
}
int mid=l+r>>1;
pos<=mid?modify(p<<1,l,mid,pos):modify(p<<1|1,mid+1,r,pos);
update(p,p<<1,p<<1|1);
}
inline void query(int p,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
for(int i=0;i<=3;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
f[4*n+1][i][j][k]=f[0][i][j][k];
update(0,4*n+1,p);
return;
}
int mid=l+r>>1;
if(x<=mid)query(p<<1,l,mid,x,y);
if(y>mid)query(p<<1|1,mid+1,r,x,y);
}
inline ll Query(int l,int r)
{
for(int i=0;i<=3;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
f[0][i][j][k]=0;
query(1,1,n,l,r);ll res=0;
for(int i=0;i<=3;i++)res+=f[0][i][1][0]+f[0][i][1][1];
return res;
}
}T1;
struct Segtree2
{
ll f[N<<2][4][2];
inline void update(int p,int p1,int p2)
{
for(int i=0;i<=1;i++)
{
f[p][0][i]=f[p1][0][i]+f[p2][0][i]+f[p1][2][i]+f[p2][1][i];
f[p][1][i]=f[p1][3][i]+f[p1][1][i];
f[p][2][i]=f[p2][3][i]+f[p2][2][i];
f[p][3][i]=0;
}
for(int i=0;i<=1;i++)for(int j=0;i+j<=1;j++)
{
f[p][0][i+j]+=f[p1][2][i]*f[p2][1][j];
f[p][1][i+j]+=f[p1][3][i]*f[p2][1][j];
f[p][2][i+j]+=f[p1][2][i]*f[p2][3][j];
f[p][3][i+j]+=f[p1][3][i]*f[p2][3][j];
}
}
inline void build(int p,int l,int r)
{
if(l==r){a[r]?f[p][3][1]=1:f[p][3][0]=1;return;}
int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
update(p,p<<1,p<<1|1);
}
inline void modify(int p,int l,int r,int pos)
{
if(l==r)
{
if(a[r])f[p][3][1]=1,f[p][3][0]=0;
else f[p][3][0]=1,f[p][3][1]=0;
return;
}
int mid=l+r>>1;
pos<=mid?modify(p<<1,l,mid,pos):modify(p<<1|1,mid+1,r,pos);
update(p,p<<1,p<<1|1);
}
inline void query(int p,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
for(int i=0;i<=3;i++)
for(int j=0;j<=1;j++)
f[4*n+1][i][j]=f[0][i][j];
update(0,4*n+1,p);
return;
}
int mid=l+r>>1;
if(x<=mid)query(p<<1,l,mid,x,y);
if(y>mid)query(p<<1|1,mid+1,r,x,y);
}
inline ll Query(int l,int r)
{
for(int i=0;i<=3;i++)
for(int j=0;j<=1;j++)
f[0][i][j]=0;
query(1,1,n,l,r);ll res=0;
for(int i=0;i<=3;i++)res+=f[0][i][1];
return res;
}
}T2;
int main()
{
//freopen("binary.in","r",stdin);
//freopen("binary.out","w",stdout);
n=getint();
for(int i=1;i<=n;i++)a[i]=getint();
T1.build(1,1,n),T2.build(1,1,n);
for(int i=1;i<=n;i++)
{
if(a[i])bit1.add(i,1);
if(i<n&&(a[i]^a[i+1]))bit2.add(i,1);
}
int op,l,r;
for(m=getint();m;m--)
{
op=getint();
if(op==1)
{
l=getint(),a[l]^=1;
T1.modify(1,1,n,l),T2.modify(1,1,n,l),bit1.add(l,a[l]?1:-1);
if(l<n)bit2.add(l,(a[l]^a[l+1])?1:-1);
if(l>1)bit2.add(l-1,(a[l-1]^a[l])?1:-1);
}
else
{
l=getint(),r=getint();ll len=r-l+1;
cout<<len*(len+1)/2-T1.Query(l,r)-T2.Query(l,r)+bit1.Query(l,r)+bit2.Query(l,r-1)<<'\n';
}
}
return 0;
}