线段树好题
(n,m,1e5)
二进制没有位除3的余数是以12121212……循环的
我们用总数减去不合法情况:
- 只有1个1,0的个数>=2(保证不重复)
- 奇数个1,0的个数<2
考虑用线段树解决
每一点存
(dl[0/1][0/1]),左端点起,0的个数,1的个数的偶奇的方案数,(dr)同理
(fl[0/1/2]),左端点起,一个1,0/1/>=2个0的方案数,(fr)同理
在记录0/1的个数,左起/右起0的个数,答案
讨论更新即可
时间复杂度(O(nlog_n))
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
const int N=1e5+4;
struct node{
int dl[2][2],dr[2][2],fl[3],fr[3],s0,s1,l0,r0,s;
//左端点起 0出现次数0/1 1的奇偶1/0 左端点起1的个数1个0的个数0/1/>=2
inline void init(){
memset(dl,0,sizeof(dl));
memset(dr,0,sizeof(dr));
memset(fl,0,sizeof(fl));
memset(fr,0,sizeof(fr));
s0=s1=l0=r0=s=0;
}
node(){init();}
inline void pre(int x){
init();
if(x)dl[0][1]=dr[0][1]=fl[0]=fr[0]=s1=s=1;
else dl[1][0]=dr[1][0]=s0=l0=r0=1;
}
inline node operator +(const node &a)const{
static node ret;
memcpy(ret.dl,dl,sizeof(dl));
memcpy(ret.fl,fl,sizeof(fl));
memcpy(ret.dr,a.dr,sizeof(a.dr));
memcpy(ret.fr,a.fr,sizeof(a.fr));
for(int i=0;i+s0<2;i++)
for(int v=0;v^2;v++)
ret.dl[s0+i][v^(s1&1)]+=a.dl[i][v];
for(int i=0;i+a.s0<2;i++)
for(int v=0;v^2;v++)
ret.dr[a.s0+i][v^(a.s1&1)]+=dr[i][v];
for(int i=0;i<3;i++){
if(!s1)ret.fl[min(2ll,i+s0)]+=a.fl[i];
if(!a.s1)ret.fr[min(2ll,i+a.s0)]+=fr[i];
}
if(s1==1&&a.l0){
ret.fl[min(2ll,s0+a.l0)]+=1;
ret.fl[2]+=a.l0-1;
}
if(a.s1==1&&r0){
ret.fr[min(2ll,a.s0+r0)]+=1;
ret.fr[2]+=r0-1;
}
ret.l0=l0+(!s1?a.l0:0);//括号括起来
ret.r0=a.r0+(!a.s1?r0:0);
ret.s0=s0+a.s0;
ret.s1=s1+a.s1;
ret.s=s+a.s;
ret.s+=dr[0][0]*(a.dl[0][1]+a.dl[1][1])+dr[0][1]*(a.dl[0][0]+a.dl[1][0])+dr[1][0]*a.dl[0][1]+dr[1][1]*a.dl[0][0];
if(r0)ret.s+=r0*(a.fl[0]+a.fl[1]+a.fl[2])-a.fl[0];
if(a.l0)ret.s+=a.l0*(fr[0]+fr[1]+fr[2])-fr[0];
return ret;
}
}t[N<<2];
#define lc (p<<1)
#define rc (p<<1|1)
int n,m,a[N<<2];
void build(int p,int l,int r){
if(l==r){
t[p].pre(a[l]);
return;
}
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
t[p]=t[lc]+t[rc];
}
void modify(int p,int l,int r,int x){
if(l==r){
t[p].pre(a[l]);
return;
}
int mid=l+r>>1;
if(x<=mid)modify(lc,l,mid,x);
else modify(rc,mid+1,r,x);
t[p]=t[lc]+t[rc];
}
node query(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return t[p];
int mid=l+r>>1;
if(qr<=mid)return query(lc,l,mid,ql,qr);
if(mid<ql)return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
signed main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
build(1,1,n);
m=read();
while(m--){
static int op,x,y;
op=read();x=read();
if(op==1){
a[x]^=1;
modify(1,1,n,x);
}
else{
y=read();
cout<<(y-x+1)*(y-x+2)/2-query(1,1,n,x,y).s<<"
";
}
}
return (0-0);
}