luogu P4428 [BJOI2018]二进制
先考虑怎样的二进制串才会被3整除.可以发现如果二进制位第\(0,2,4...2n\)位如果为\(1\),那么在模3意义下为1,如果二进制位第\(1,3,5...2n+1\)位如果为\(1\),那么在模3意义下为-1.所以也就是位置上是1的奇二进制位个数减位置上是1的偶二进制位个数要被3整除
在这种条件下,如果区间内1的个数为偶数显然可以从最低位开始依次放使得被3整除,如果为奇数,那么先把除了最后三个1以外的1按照偶数的情况处理,然后这三个1中间各插入一个0,也就是\(...0101011...1\).那么,不合法的情况就只剩下有区间内奇数个1同时0的个数\(<2\),或者是区间内只有一个1
合法区间比较麻烦,改为求总区间个数-不合法区间个数.为了不算重,把不合法条件改为只剩下有区间内奇数个1同时0的个数\(<2\),或者是区间内只有一个1同时\(\ge 2\).我们用线段树维护这些区间个数,对每个节点记一个\(ls_{i,j}\)表示左端点为这个线段树节点对应区间左端点的区间中,1的个数奇偶性为\(0/1\),0的个数为\(0/1\)的区间个数,\(rs_{i,j}\)表示的是右端点为线段树节点右端点的相应的区间个数;\(lz_{i,j}\)表示左端点为线段树节点左端点的区间中,1的个数为\(0/1\),0的个数为\(0/1/\ge 2\)的区间个数,\(rz_{i,j}\)表示的是右端点为线段树节点右端点的相应的区间个数.以及分别记录区间\(0/1\)个数和不合法区间个数,每次合并两个节点,就计算跨越这两个节点的区间信息,可能需要一点点讨论,这里不再赘述
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=1e5+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
struct node
{
LL c0,c1,s;
LL ls[2][2],rs[2][2];
LL lz[2][3],rz[2][3];
void clr(){memset(ls,0,sizeof(ls)),memset(rs,0,sizeof(rs)),memset(lz,0,sizeof(lz)),memset(rz,0,sizeof(rz)),c0=c1=s=0;}
node(){}
node(int x)
{
memset(ls,0,sizeof(ls)),memset(rs,0,sizeof(rs)),memset(lz,0,sizeof(lz)),memset(rz,0,sizeof(rz)),c0=c1=s=0;
if(!x)
{
c0=1;
ls[0][1]=rs[0][1]=lz[0][1]=rz[0][1]=1;
}
else
{
s=c1=1;
ls[1][0]=rs[1][0]=lz[1][0]=rz[1][0]=1;
}
}
}s[N<<2],an;
node merg(node aa,node bb)
{
an.clr();
an.c0=aa.c0+bb.c0;
an.c1=aa.c1+bb.c1;
an.s=aa.s+bb.s;
for(int i=0;i<=1;++i)
for(int j=0;j<=1;++j)
{
an.ls[i][j]+=aa.ls[i][j];
an.rs[i][j]+=bb.rs[i][j];
if(aa.c0+j<=1) an.ls[(aa.c1&1)^i][aa.c0+j]+=bb.ls[i][j];
if(bb.c0+j<=1) an.rs[(bb.c1&1)^i][bb.c0+j]+=aa.rs[i][j];
}
for(int i=0;i<=1;++i)
for(int j=0;j<=1;++j)
for(int k=0;k<=1;++k)
for(int l=0;l<=1;++l)
if((i^k)==1&&j+l<=1) an.s+=aa.rs[i][j]*bb.ls[k][l];
for(int i=0;i<=1;++i)
for(int j=0;j<=2;++j)
{
an.lz[i][j]+=aa.lz[i][j];
an.rz[i][j]+=bb.rz[i][j];
if(aa.c1+i<=1) an.lz[aa.c1+i][min(aa.c0+j,2ll)]+=bb.lz[i][j];
if(bb.c1+i<=1) an.rz[bb.c1+i][min(bb.c0+j,2ll)]+=aa.rz[i][j];
}
for(int i=0;i<=1;++i)
for(int j=0;j<=2;++j)
for(int k=0;k<=1;++k)
for(int l=0;l<=2;++l)
if(i+k==1&&j+l>=2) an.s+=aa.rz[i][j]*bb.lz[k][l];
return an;
}
int n,a[N];
void psup(int o){s[o]=merg(s[o<<1],s[o<<1|1]);}
void modif(int o,int l,int r,int lx)
{
if(l==r){a[l]^=1;s[o]=node(a[l]);return;}
int mid=(l+r)>>1;
if(lx<=mid) modif(o<<1,l,mid,lx);
else modif(o<<1|1,mid+1,r,lx);
psup(o);
}
node quer(int o,int l,int r,int ll,int rr)
{
if(ll<=l&&r<=rr) return s[o];
int mid=(l+r)>>1;
if(rr<=mid) return quer(o<<1,l,mid,ll,rr);
if(ll>mid) return quer(o<<1|1,mid+1,r,ll,rr);
return merg(quer(o<<1,l,mid,ll,mid),quer(o<<1|1,mid+1,r,mid+1,rr));
}
void bui(int o,int l,int r)
{
if(l==r){s[o]=node(a[l]);return;}
int mid=(l+r)>>1;
bui(o<<1,l,mid),bui(o<<1|1,mid+1,r);
psup(o);
}
int main()
{
n=rd();
for(int i=1;i<=n;++i) a[i]=rd();
bui(1,1,n);
int q=rd();
while(q--)
{
int op=rd();
if(op==1) modif(1,1,n,rd());
else
{
int l=rd(),r=rd();
printf("%lld\n",1ll*(r-l+1)*(r-l+2)/2-quer(1,1,n,l,r).s);
}
}
return 0;
}
luogu P4428 [BJOI2018]二进制的更多相关文章
- Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)
题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...
- 【BZOJ5294】[BJOI2018]二进制(线段树)
[BZOJ5294][BJOI2018]二进制(线段树) 题面 BZOJ 洛谷 题解 二进制串在模\(3\)意义下,每一位代表的余数显然是\(121212\)这样子交替出现的. 其实换种方法看,就是\ ...
- 2019.02.12 bzoj5294: [Bjoi2018]二进制(线段树)
传送门 题意简述: 给出一个长度为nnn的二进制串. 你需要支持如下操作: 修改每个位置:1变0,0变1 询问对于一个区间的子二进制串有多少满足重排之后转回十进制值为333的倍数(允许前导000). ...
- bzoj 5294: [Bjoi2018]二进制
Description pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是333 的倍数.他想研究对于二进 制,是否也有类似的性质.于是他生成了一个长为n 的二进制串,希望 ...
- Luogu P4932 浏览器(二进制)
P4932 浏览器 题意 题目背景 __stdcall在用\(Edge\)玩\(slay\)的时候,鼠标会经常失灵,这让她十分痛苦,因此她决定也要让你们感受一下\(Edge\)制造的痛苦. 题目描述 ...
- BZOJ5294 BJOI2018 二进制 线段树
传送门 因为每一位\(\mod 3\)的值为\(1,2,1,2,...\),也就相当于\(1,-1,1,-1,...\) 所以当某个区间的\(1\)的个数为偶数的时候,一定是可行的,只要把这若干个\( ...
- [Bjoi2018]二进制
题解: 首先发现性质 只有1个1的区间 或者 奇数个1且0的个数少于2这个区间是不合法的 然后这个东西暴力是比较好处理的 刚开始写的比较傻逼,分几种情况 先把0,1缩在一起 1.k1个0+1+k2个0 ...
- Luogu P4427 [BJOI2018]求和
这是一道巨狗题,我已无力吐槽为什么我怎么写都不过 我们对于这种无修改的边权题目有一个经典的树上差分套路: \(ans=sum_x+sum_y-2\cdot sum_{LCA(x,y)}\) 这里的\( ...
- BZOJ5294 [BJOI2018] 二进制 【线段树】
BJOI的题目感觉有点难写 题目分析: 首先推一波结论.接下来的一切都在模3意义下 现在我们将二进制位重组,不难发现的是2^0≡1,2^1≡2,2^2≡1,2^3≡2....所以我们考虑这样的式子 2 ...
随机推荐
- vuejs2从入门到精通与项目开发实战
vuejs2从入门到精通:一.基础部分0.课件1.介绍2.vue实例3.模板语法4.计算属性和观察者5.Class与Style绑定6.条件渲染7.列表渲染8.事件处理9.表单输入绑定10.1.组件(1 ...
- mac 安装laravel
安装laravel之前先安装composer 使用 curl 指令下载: curl -sS https://getcomposer.org/installer | php 或是沒有安裝 curl ,也 ...
- P4095 [HEOI2013]Eden 的新背包问题
P4095 [HEOI2013]Eden 的新背包问题 题解 既然假定第 i 个物品不可以选,那么我们就设置两个数组 dpl[][] 正序选前i个物品,dpr[][] 倒序选前i个物品 ,价格不超过 ...
- Jedis的Publish/Subscribe功能的使用
redis内置了发布/订阅功能,可以作为消息机制使用.所以这里主要使用Jedis的Publish/Subscribe功能. 1.使用Spring来配置Jedis连接池 <!-- pool配置 - ...
- HashMap 怎么 hash?又如何 map?
HashMap 是 Java 中 Map 的一个实现类,它是一个双列结构(数据+链表),这样的结构使得它的查询和插入效率都很高.HashMap 允许 null 键和值,它的键唯一,元素的存储无序,并且 ...
- 安装mysql报Requires: libc.so.6(GLIBC_2.17)(64bit)
Error: Package: mysql-community-server-5.6.40-2.el7.x86_64 (mysql56-community) Requires: libc.so.6(G ...
- sqlalchemy 的操作
使用PyMySQL的前提: 1. 先建好表 2. 自己动手需要手动去写多条SQL语句 改进: 类 ------> 表 实例化 -> 数据 这种思想叫:ORM(Object Relatio ...
- 【jQuery】attr()、prop()、css() 的区别(转载)
.attr( ) 可以设置元素的属性(也就是给元素新增加一个原来并不存在的属性)也可以获取元素的本来就有的属性以及额外设置的属性.如果要获取的属性没有设置,那么获取到的结果是 undefined; . ...
- 2019年最新Web安全攻防班课程
咨询请加QQ:1373721311 或 2644148223 课程核心大纲总览 Web安全攻防班以业界权威的OWASP TOP 10的漏洞为主干课程.更加详细教学思维导图可访问如下链接:https:/ ...
- Linux文件属性之Linux文件删除重要原理详解
Linux下文件删除的原理 只要dongdaxiafile(源文件).服务进程.dongdaxiaflie_hard_link(硬链接文件)三个中的任意一个存在文件不会被删除.