# 「BJOI2018」二进制

## 题面描述

pupil 发现对于一个十进制数，无论怎么将其的数字重新排列，均不影响其是不是 $3$ 的倍数。他想研究对于二进制，是否也有类似的性质。

## 题解

P.S.：经本人确认已女装

1.$‘1’$的个数为奇数
2.$‘1’$的个数为1或$‘0’$的个数小于2

## 代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int Q=1<<17,P=1<<20;
#define ll long long
int a[Q];
struct dt{
int l11,l12;
int r11,r12;
int l01,l02;
int r01,r02;
int len;
ll f;
}p[Q<<2],ch[2];
void Do()
{
ch[0]=(dt){1,0,1,0,0,0,0,0,1,0};
ch[1]=(dt){0,1,0,1,1,0,1,0,1,1};
}
// 0->even 1->odd
int G(int ty,int x)
{return (x+ty)>>1;}
int G(int ty,int x,int y)
{return G(ty,y)-G(ty,x-1);}
dt operator+(dt a,dt b)
{
dt tmp;
if(a.l11!=a.len){
tmp.l11=a.l11;
if(a.l11+a.l12!=a.len)tmp.l12=a.l12;
else tmp.l12=a.l12+b.l11;
}
else{
tmp.l11=a.len+b.l11;
tmp.l12=b.l12;
}
if(b.r11!=b.len){
tmp.r11=b.r11;
if(b.r11+b.r12!=b.len)tmp.r12=b.r12;
else tmp.r12=b.r12+a.r11;
}
else{
tmp.r11=b.len+a.r11;
tmp.r12=a.r12;
}
if(a.l01<a.len){
tmp.l01=a.l01;
if(a.l01+a.l02+1<a.len)tmp.l02=a.l02;
else tmp.l02=a.l02+b.l01;
}
else{
tmp.l01=a.len+b.l01;
tmp.l02=b.l02;
}
//
if(b.r01<b.len){
tmp.r01=b.r01;
if(b.r01+b.r02+1<b.len)tmp.r02=b.r02;
else tmp.r02=b.r02+a.r01;
}
else{
tmp.r01=b.len+a.r01;
tmp.r02=a.r02;
}
tmp.len=a.len+b.len;
tmp.f=a.f+b.f;
tmp.f+=1LL*a.r11*b.l12+1LL*b.l11*a.r12;
tmp.f+=1LL*G(0,a.r01)*G(1,b.l01)+1LL*G(1,a.r01)*G(0,b.l01);
if(a.r01!=a.len)tmp.f+=1LL*G(0,a.r01,a.r01+a.r02)*G(1,b.l01)+1LL*G(1,a.r01,a.r01+a.r02)*G(0,b.l01);
if(b.l01!=b.len)tmp.f+=1LL*G(0,b.l01,b.l01+b.l02)*G(1,a.r01)+1LL*G(1,b.l01,b.l01+b.l02)*G(0,a.r01);
if((a.r11==0)^(b.l11==0))tmp.f--;
return tmp;
}
#define mid ((l+r)>>1)
#define ls (now<<1)
#define rs (now<<1|1)
void upd(int now)
{p[now]=p[ls]+p[rs];}
void Init(int now,int l,int r)
{
if(l==r){
p[now]=ch[a[l]];
return;
}
Init(ls,l,mid),Init(rs,mid+1,r);
upd(now);
}
void MDF(int now,int l,int r,int x)
{
if(l==r){
p[now]=ch[a[x]];
return;
}
if(x<=mid)MDF(ls,l,mid,x);
else MDF(rs,mid+1,r,x);
upd(now);
}
dt Gans(int now,int l,int r,int x,int y)
{
if(x<=l&&y>=r)return p[now];
if(y<=mid)return Gans(ls,l,mid,x,y);
if(x>mid)return Gans(rs,mid+1,r,x,y);
return Gans(ls,l,mid,x,y)+Gans(rs,mid+1,r,x,y);
}
int main()
{
Do();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
Init(1,1,n);
int m;
scanf("%d",&m);
for(int p=1;p<=m;p++){
int ty,x,y;
scanf("%d%d",&ty,&x);
if(ty==1){
a[x]^=1;
MDF(1,1,n,x);
}
else{
scanf("%d",&y);
printf("%lld\n",1LL*(y-x+1)*(y-x+2)/2LL-Gans(1,1,n,x,y).f);
}
}
return 0;
}
posted @ 2019-03-21 20:13 蒟蒻小果冻 阅读(...) 评论(...)  编辑 收藏