传送门
题意简述:
给出一个长度为nnn的二进制串。
你需要支持如下操作:

  1. 修改每个位置:1变0,0变1
  2. 询问对于一个区间的子二进制串有多少满足重排之后转回十进制值为333的倍数(允许前导000)。

思路:
考虑一个xxx位的包含有yyy个111的二进制串,它是333的倍数当如下任意一个条件成立:

  1. yyy是偶数。
  2. yyy是大于111的奇数且x−y>=2x-y>=2x−y>=2

emmmmemmmmemmmm感觉不是很好维护。
于是我们正难则反,跑去求不合法的方案数,这个二进制串不合法如下任意一个条件成立:

  1. yyy是奇数大于111且x−y&lt;2x-y&lt;2x−y<2
  2. y=1y=1y=1

这个答案可以用线段树维护了(其实上面的也可以只是感觉不太好写)。
我们定义两类状态:

  • C0/1,0/1,0/1,0/1C_{0/1,0/1,0/1,0/1}C0/1,0/1,0/1,0/1​表示从区间左/右端点开始的连续一段二进制串,满足其中有偶/奇数个111,串中111的个数不大于/大于111个,串中有0/10/10/1个000的这样的二进制串个数。
  • D0/1,0/1D_{0/1,0/1}D0/1,0/1​表示从区间左/右端点开始的连续一段二进制串,满足其中有0/10/10/1个111的这样的二进制串的个数。

然后分类转移一下即可。
代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=1e5+5;
typedef long long ll;
int n;
bool a[N];
inline int read(){int ans=0;char ch=getchar();while(!isdigit(ch))ch=getchar();while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();return ans;
}
inline int add(const ll&a,const ll&b){return !a*b?0:a+b;}
namespace SGT{#define lc (p<<1)#define rc (p<<1|1)#define mid (T[p].l+T[p].r>>1)struct Node{int l,r,det;ll ans,c[2][2][2][2],d[2][2];}T[N<<2];inline Node operator+(const Node&a,const Node&b){Node ret;ret.l=a.l,ret.r=b.r,ret.det=a.det+b.det,ret.ans=a.ans+b.ans,memset(ret.c,0,sizeof(ret.c));ret.d[0][0]=a.d[0][0]+(a.det?0:b.d[0][0]);ret.d[0][1]=a.d[0][1]+(a.det<2?b.d[0][1-a.det]:0);ret.d[1][0]=b.d[1][0]+(b.det?0:a.d[1][0]);ret.d[1][1]=b.d[1][1]+(b.det<2?a.d[1][1-b.det]:0);for(ri i=0;i<2;++i)for(ri j=0;j<2;++j)for(ri k=0;k<2;++k)ret.c[0][i][j][k]=a.c[0][i][j][k],ret.c[1][i][j][k]=b.c[1][i][j][k];int tl=a.r-a.l+1-a.det,tr=b.r-b.l+1-b.det;for(ri k=0;k+tl<2;++k){ret.c[0][0][0][k+tl]+=a.det?0:b.c[0][0][0][k];ret.c[0][0][1][k+tl]+=b.c[0][a.det&1][1][k]+(a.det?b.c[0][a.det&1][0][k]:0);ret.c[0][1][0][k+tl]+=a.det<2?b.c[0][1-a.det][0][k]:0;ret.c[0][1][1][k+tl]+=b.c[0][(a.det&1)^1][1][k]+(a.det>1?b.c[0][(a.det&1)^1][0][k]:0);}for(ri k=0;k+tr<2;++k){ret.c[1][0][0][k+tr]+=b.det?0:a.c[1][0][0][k];ret.c[1][0][1][k+tr]+=a.c[1][b.det&1][1][k]+(b.det?a.c[1][b.det&1][0][k]:0);ret.c[1][1][0][k+tr]+=b.det<2?a.c[1][1-b.det][0][k]:0;ret.c[1][1][1][k+tr]+=a.c[1][(b.det&1)^1][1][k]+(b.det>1?a.c[1][(b.det&1)^1][0][k]:0);}for(ri i=0;i<2;++i)for(ri j=0;i+j<2;++j){ret.ans+=a.c[1][0][0][i]*b.c[0][1][1][j]+a.c[1][0][1][i]*b.c[0][1][1][j]+a.c[1][0][1][i]*b.c[0][1][0][j];ret.ans+=a.c[1][1][0][i]*b.c[0][0][1][j]+a.c[1][1][1][i]*b.c[0][0][1][j]+a.c[1][1][1][i]*b.c[0][0][0][j];}ret.ans+=a.d[1][0]*b.d[0][1]+a.d[1][1]*b.d[0][0];return ret;}inline void solve(int p){T[p].ans=T[p].det=0,memset(T[p].c,0,sizeof(T[p].c)),memset(T[p].d,0,sizeof(T[p].d));if(a[T[p].l])T[p].ans=T[p].det=T[p].c[0][1][0][0]=T[p].c[1][1][0][0]=T[p].d[0][1]=T[p].d[1][1]=1;else T[p].c[0][0][0][1]=T[p].c[1][0][0][1]=T[p].d[0][0]=T[p].d[1][0]=1;}inline void build(int p,int l,int r){T[p].l=l,T[p].r=r;if(l==r)return solve(p);build(lc,l,mid),build(rc,mid+1,r),T[p]=T[lc]+T[rc];}inline void update(int p,int k){if(T[p].l==T[p].r)return solve(p);update(k<=mid?lc:rc,k),T[p]=T[lc]+T[rc];}inline Node query(int p,int ql,int qr){if(ql<=T[p].l&&T[p].r<=qr)return T[p];if(qr<=mid)return query(lc,ql,qr);if(ql>mid)return query(rc,ql,qr);return query(lc,ql,mid)+query(rc,mid+1,qr);}
}
int main(){n=read();for(ri i=1;i<=n;++i)a[i]=read();SGT::build(1,1,n);for(ri tt=read(),op,l,r;tt;--tt){op=read();if(op==1)a[l=read()]^=1,SGT::update(1,l);else l=read(),r=read(),cout<<(ll)(r-l+1)*(r-l+2)/2-SGT::query(1,l,r).ans<<'\n';}return 0;
}

bzoj5294: [Bjoi2018]二进制(线段树)相关推荐

  1. 中国石油大学(华东)暑期集训--二进制(BZOJ5294)【线段树】

    问题 C: 二进制 时间限制: 1 Sec  内存限制: 128 MB 提交: 8  解决: 2 [提交] [状态] [讨论版] [命题人:] 题目描述 pupil发现对于一个十进制数,无论怎么将其的 ...

  2. Codeforces Round #807 (Div. 2) E. Mark and Professor Koro 二进制/线段树

    题目分析 模拟题目不难发现,实际上擦除操作就是在模拟二进制加法进位.那么可以得到原题意的转述: 将每个 a [ i ] a[i] a[i]看作 2 a [ i ] 2^{a[i]} 2a[i],维护整 ...

  3. 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)

    [BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ...

  4. Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))...

    题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...

  5. 皮卡丘的梦想2(线段树+二进制状态压缩)

    Description 一天,一只住在 501 实验室的皮卡丘决定发奋学习,成为像 LeiQ 一样的巨巨,于是他向镇上的贤者金桔请教如何才能进化成一只雷丘. 金桔告诉他需要进化石才能进化,并给了他一个 ...

  6. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  7. 【线段树】二进制(luogu 4428)

    正题 luogu 4428 题目大意 给你一个01串,让你进行一下两种操作: 1.将其中一位取反 2.问你某一段中有多少个子串满足有一种排列方案,使得组成的二进制数是3的倍数 解题思路 不难发现,因为 ...

  8. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  9. 2017年ICPC西安邀请赛A、XOR(线段树套线性基 + 思维)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目传送门 Problem 给你 nnn 和 nnn 个整数的数组 aaa,以及kkk和qqq,有 q ...

  10. 2018.06.28 与或(线段树)

    #与或 描述 样例输入 5 8 1 3 2 5 4 3 1 3 2 1 1 5 3 1 3 1 1 4 6 2 3 4 1 3 2 3 2 2 3 4 3 1 5 **样例输出 ** 3 5 3 7 ...

最新文章

  1. PYTHON 写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者...
  2. mysql数据库语句q_mysql数据库命令大全,mysql基本命令大全
  3. access下如何配置两个vlan_【新华三】网络工程师 H3C如何配置VLAN-trunk 二层隔离技术...
  4. 神经网络上采样之:反卷积
  5. MySQL 多实例给root用户创建密码
  6. 让Windows2008R2也能进入手柄设置(游戏控制器设置)
  7. 二级考试java模拟考试_2017年计算机二级考试Java模拟试题及答案
  8. 处女座|处女座性格分析
  9. Java中随机数的原理,以及使用时的注意点
  10. 垃圾收集算法,垃圾收集器_为什么我不能关闭垃圾收集器?
  11. Platform Invoke and Marshaling Data: [1/3]
  12. 实验吧之【Forms、天网管理系统】
  13. redis数据结构-hash
  14. VMware使用OVFTool导入虚拟机
  15. 【零基础学JS -2】 适合编写JS的编辑器
  16. openjdk和jdk_OpenJDK和HashMap…。 安全地教老狗新技巧(堆!)
  17. 2022施工员-土建方向-通用基础(施工员)理论题库模拟考试平台操作
  18. 生成式对抗网络(GAN)原理推导与网络构建思路
  19. 第七章 MyBatis 缓存配置
  20. 文件上传漏洞初步解析(个人浅薄理解)

热门文章

  1. 用户认证授权系统方案思考
  2. 简体中文转繁体的python简单实现
  3. xp系统远程桌面关闭计算机,系统是xp在本机开启远程桌面后,别人使用远程桌面连接我的电脑,我的电脑就会出现蓝屏停止代码是0x0000007f...
  4. 达梦数据库大小写这个参数敏感怎样设置
  5. 大数据分页实现与性能优化【转】
  6. 水星如何设置虚拟机服务器,水星mercury路由器电脑怎么设置?
  7. 环境样品中病毒的富集与检测方法
  8. 2021年北京高考成绩排名查询,北京2021高考成绩排名榜单,北京各高中高考成绩喜报...
  9. 服务器托管费用一般是多少
  10. android八方向手势,Android开发中顺时针逆时针滑动手势的识别算法