问题 C: 二进制

时间限制: 1 Sec  内存限制: 128 MB
提交: 8  解决: 2
[提交] [状态] [讨论版] [命题人:]

题目描述

pupil发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是3的倍数。他想研究对于二进制,是否也有类似的性质。于是他生成了一个长为n的二进制串,希望你对于这个二进制串的一个子区间,能求出其有多少位置不同的连续子串,满足在重新排列后(可包含前导0)是一个3的倍数。两个位置不同的子区间指开始位置不同或结束位置不同。由于他想尝试尽量多的情况,他有时会修改串中的一个位置,并且会进行多次询问。

输入

输入第一行包含一个正整数n,表示二进制数的长度。
之后一行n个空格隔开的整数,保证均是0或1,表示该二进制串。
之后一行一个整数m,表示询问和修改的总次数。
之后m行每行为1 i,表示pupil修改了串的第i个位置(0变成1或1变成0),或2 l r,表示pupil询问的子区间是[l,r]。
串的下标从1开始。

输出

对于每次询问,输出一行一个整数表示对应该询问的结果。

样例输入

4
1 0 1 0
3
2 1 3
1 3
2 3 4

样例输出

2
3

提示

对于第一个询问,区间[2,2]只有数字0,是3的倍数,区间[1,3]可以重排成011(2)=3(10),是3的倍数,其他区间均不能重排成3的倍数。
对于第二个询问,全部三个区间均能重排成3的倍数(注意00也是合法的)。

对于20%的数据,1≤n,m≤100;
对于50%的数据,1≤n,m≤5000;
对于100%的数据,1≤n,m≤100000,l≤r。

Solution:

设cnt0,cnt1分别为[l,r]区间内的1和0的个数,易得:
  1. if cnt1==1 => 不可整除3
  2. if cnt1&1 and cnt0<2 => 不可整除3

  简单证明上述结论:

    显然结论1是成立的(1<<n不可能整除3),当cnt1为偶数时,显然也一定可以整除3,而当cnt1&1时:

    先考虑这种情况,将一个二进制数将其两位两位拆分并求和得到sum,显然如果 sum%3==0 ,则该二进制数的十进制一定可以整除3。

    如:111010001=>(01,11,01,00,01),sum=1+3+1+0+1=6。

    那么,对于奇数个1,从中挑出cnt1-3个“1”两两组合,确保对sum%3的结果无贡献后,再看剩下的3个“1”的情况:

      ①、sum(111)=4 无法整除。【区间内无0】

      ②、sum(1101)=4,sum(1011)=5 无法整除。【区间内只含有一个0】

      ③、sum(10101)=3 可整除。【区间内至少含有两个0】

  综上:

    我们用线段树去维护上述两种不合法情况,再用【总数-不合法数=合法数】来得到答案。

    其中,dl/dr[2][2] 代表经过左右节点后:cnt0=0/1,cnt1&1?1:0。

    fl/fr[3] 代表经过左右节点后:满足(cnt1==1 and cnt0==0/1)的方案数。

    L/R表示经过左右节点后,连续0的长度。

代码:

 #include <iostream>
#include <string>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#define range(i,a,b) for(auto i=a;i<=b;++i)
#define LL long long
#define ULL unsigned long long
#define elif else if
#define itrange(i,a,b) for(auto i=a;i!=b;++i)
#define rerange(i,a,b) for(auto i=a;i>=b;--i)
#define fill(arr,tmp) memset(arr,tmp,sizeof(arr))
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
int n,m,op,l,r,A[int(1e5+)];
class SegTree{
private:
struct node{
LL s,dl[][],dr[][],fl[],fr[],L,R;
int cnt0,cnt1;
void reset(){
range(i,,)range(j,,)dl[i][j]=dr[i][j]=;
fl[]=fl[]=fr[]=fr[]=fl[]=fr[]=L=R=s=cnt0=cnt1=;
}
node(){reset();}
}tree[int(1e5+)<<];
node comb(node A,node B){
node tmp;
range(i,,)range(j,,){
tmp.dl[i][j]+=A.dl[i][j];
tmp.dr[i][j]+=B.dr[i][j];
if(i>=A.cnt0)tmp.dl[i][j]+=B.dl[i-A.cnt0][j^(A.cnt1&)];
if(i>=B.cnt0)tmp.dr[i][j]+=A.dr[i-B.cnt0][j^(B.cnt1&)];
}
range(i,,){
tmp.fl[i]+=A.fl[i];
tmp.fr[i]+=B.fr[i];
if(!A.cnt1)tmp.fl[min(,i+A.cnt0)]+=B.fl[i];
if(!B.cnt1)tmp.fr[min(,i+B.cnt0)]+=A.fr[i];
}
if(A.cnt1== and B.L){
++tmp.fl[min(2LL,A.cnt0+B.L)];
tmp.fl[]+=B.L-;
}
if(B.cnt1== and A.R){
++tmp.fr[min(2LL,B.cnt0+A.R)];
tmp.fr[]+=A.R-;
}
tmp.L=(!A.cnt1?A.cnt0+B.L:A.L);tmp.R=(!B.cnt1?B.cnt0+A.R:B.R);
tmp.cnt0=A.cnt0+B.cnt0;tmp.cnt1=A.cnt1+B.cnt1;tmp.s+=A.s+B.s;
tmp.s+=A.dr[][]*(B.dl[][]+B.dl[][])+A.dr[][]*B.dl[][];
tmp.s+=A.dr[][]*(B.dl[][]+B.dl[][])+A.dr[][]*B.dl[][];
if(B.L)tmp.s+=(A.fr[]+A.fr[])*B.L+A.fr[]*(B.L-);
if(A.R)tmp.s+=(B.fl[]+B.fl[])*A.R+B.fl[]*(A.R-);
return tmp;
}
void pushup(node &tmp,int x){
tmp.reset();
if(x)tmp.s=tmp.fl[]=tmp.fr[]=tmp.dl[][]=tmp.dr[][]=tmp.cnt1=;
else tmp.dl[][]=tmp.dr[][]=tmp.L=tmp.R=tmp.cnt0=;
};
public:
void build(int l,int r,int rt=){
if(l==r){
pushup(tree[rt],A[l]);
return;
}
int m=(l+r)>>;
build(l,m,rt<<);
build(m+,r,rt<<|);
tree[rt]=comb(tree[rt<<],tree[rt<<|]);
}
void update(int l,int r,int rt,int L){
if(l==r){
pushup(tree[rt],A[l]);
return;
}
int m=(l+r)>>;
if(L<=m)update(l,m,rt<<,L);
else update(m+,r,rt<<|,L);
tree[rt]=comb(tree[rt<<],tree[rt<<|]);
}
node query(int l,int r,int rt,int L,int R){
if(L<=l and r<=R)return tree[rt];
int m=(l+r)>>;
if(R<=m)return query(l,m,rt<<,L,R);
if(L>m)return query(m+,r,rt<<|,L,R);
return comb(query(l,m,rt<<,L,m),query(m+,r,rt<<|,m+,R));
}
}segTree;
void init(){
scanf("%d",&n);
range(i,,n)scanf("%d",A+i);
segTree.build(,n);
scanf("%d",&m);
}
void solve(){
while(m--){
scanf("%d%d",&op,&l);
if(op&)A[l]^=,segTree.update(,n,,l);
else{
scanf("%d",&r);
printf("%lld\n",1LL*(r-l+)*(r-l+)/-segTree.query(,n,,l,r).s);
}
}
}
int main() {
init();
solve();
return ;
}

中国石油大学(华东)暑期集训--二进制(BZOJ5294)【线段树】的更多相关文章

  1. 【BZOJ5294】[BJOI2018]二进制(线段树)

    [BZOJ5294][BJOI2018]二进制(线段树) 题面 BZOJ 洛谷 题解 二进制串在模\(3\)意义下,每一位代表的余数显然是\(121212\)这样子交替出现的. 其实换种方法看,就是\ ...

  2. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  3. 2019.02.12 bzoj5294: [Bjoi2018]二进制(线段树)

    传送门 题意简述: 给出一个长度为nnn的二进制串. 你需要支持如下操作: 修改每个位置:1变0,0变1 询问对于一个区间的子二进制串有多少满足重排之后转回十进制值为333的倍数(允许前导000). ...

  4. BZOJ5294 BJOI2018二进制(线段树)

    二进制数能被3整除相当于奇数.偶数位上1的个数模3同余.那么如果有偶数个1,一定存在重排方案使其合法:否则则要求至少有两个0且至少有3个1,这样可以给奇数位单独安排3个1. 考虑线段树维护区间内的一堆 ...

  5. BZOJ5294 [BJOI2018] 二进制 【线段树】

    BJOI的题目感觉有点难写 题目分析: 首先推一波结论.接下来的一切都在模3意义下 现在我们将二进制位重组,不难发现的是2^0≡1,2^1≡2,2^2≡1,2^3≡2....所以我们考虑这样的式子 2 ...

  6. Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)

    题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...

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

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

  8. 洛谷P4428二进制 [BJOI2018] 线段树

    正解:线段树 解题报告: 传送门! 话说开始看到这题的时候我想得hin简单 因为关于%3有个性质就是说一个数的各个位数之和%3=这个数%3嘛,小学基础知识? 我就想着,就直接建一棵树,只是这棵树要用个 ...

  9. HZNU-ACM寒假集训Day5小结 线段树 树状数组

    线段树 什么时候用线段树 1.统计量可合并 2.修改量可合并 3.通过统计量可直接修改统计量 一句话:满足区间加法即可使用线段树维护信息 理解Lazy Tage 蓝色是要把信息及时维护的节点,红色是本 ...

随机推荐

  1. cookie与session的区别与应用

    通常我们所说的浏览器自动保存密码,下次不用登陆,提示一次就不再出现的内容,大部分通过cookie或者session来实现的. cookie的概念 cookie是浏览器(User Agent)访问一些网 ...

  2. 牛客网刷题(纯java题型 1~30题)

    牛客网刷题(纯java题型 1~30题) 应该是先extend,然后implement class test extends A implements B { public static void m ...

  3. 完全背包问题入门 (dp)

    问题描述: 有n种重量和价值分别为Wi,Vi的物品,从这些中挑选出总重量不超过W的物品,求出挑选物品的价值总和的最大值,每种物品可以挑选任意多件. 分析: 令dp[i+1][j]表示从前i件物品中挑选 ...

  4. ...args剩余参数用法

      剩余参数语法允许我们将一个不定数量的参数表示为一个数组. function sum(...theArgs) { return theArgs.reduce((previous, current) ...

  5. charles & Fiddle

    一.Charles Charles是在Mac下常用的截取网络封包的工具,在做移动端开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析.Charles通过将自己设置成系统的网络访问 ...

  6. js_在原有的日期上添加天数输出添加后的日期

    开始编码工作也有段时间了,想想没有留下点什么,有点遗憾.学到的一些经验,写写,分享一下.也给自己整理一下. 今天分享一下,在原有的日期上添加天数输出添加后的日期.开始做的时候,简单的思路是,直接用ne ...

  7. SpringCloud Feign重试详解

    摘要: 今天在生产环境发生了数据库进程卡死的现象,除了sql因为全量更新,没加索引的原因,最主要还是我们的接口的服务器端接口出现问题了.忽视了更新接口的幂等性,以及调用方feign client的重试 ...

  8. node启动服务

    npm install http-server -g http-server ipconfig查看当前ip 手机可访问第一个网址.

  9. Caffe学习笔记4图像特征进行可视化

    Caffe学习笔记4图像特征进行可视化 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hit201 ...

  10. "Flags mismatch irq" register interrupt handler error

    Question : When you see the log "Flags mismatch irq ............", maybe you use the same ...