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

问题 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的长度。

代码:

  1 #include <iostream>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cmath>
  5 #include <cstring>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <queue>
  9 #include <deque>
 10 #include <map>
 11 #include <set>
 12 #define range(i,a,b) for(auto i=a;i<=b;++i)
 13 #define LL long long
 14 #define ULL unsigned long long
 15 #define elif else if
 16 #define itrange(i,a,b) for(auto i=a;i!=b;++i)
 17 #define rerange(i,a,b) for(auto i=a;i>=b;--i)
 18 #define fill(arr,tmp) memset(arr,tmp,sizeof(arr))
 19 #define IOS ios::sync_with_stdio(false);cin.tie(0)
 20 using namespace std;
 21 int n,m,op,l,r,A[int(1e5+5)];
 22 class SegTree{
 23 private:
 24     struct node{
 25         LL s,dl[2][2],dr[2][2],fl[3],fr[3],L,R;
 26         int cnt0,cnt1;
 27         void reset(){
 28             range(i,0,1)range(j,0,1)dl[i][j]=dr[i][j]=0;
 29             fl[0]=fl[1]=fr[0]=fr[1]=fl[2]=fr[2]=L=R=s=cnt0=cnt1=0;
 30         }
 31         node(){reset();}
 32     }tree[int(1e5+5)<<2];
 33     node comb(node A,node B){
 34         node tmp;
 35         range(i,0,1)range(j,0,1){
 36             tmp.dl[i][j]+=A.dl[i][j];
 37             tmp.dr[i][j]+=B.dr[i][j];
 38             if(i>=A.cnt0)tmp.dl[i][j]+=B.dl[i-A.cnt0][j^(A.cnt1&1)];
 39             if(i>=B.cnt0)tmp.dr[i][j]+=A.dr[i-B.cnt0][j^(B.cnt1&1)];
 40         }
 41         range(i,0,2){
 42             tmp.fl[i]+=A.fl[i];
 43             tmp.fr[i]+=B.fr[i];
 44             if(!A.cnt1)tmp.fl[min(2,i+A.cnt0)]+=B.fl[i];
 45             if(!B.cnt1)tmp.fr[min(2,i+B.cnt0)]+=A.fr[i];
 46         }
 47         if(A.cnt1==1 and B.L){
 48             ++tmp.fl[min(2LL,A.cnt0+B.L)];
 49             tmp.fl[2]+=B.L-1;
 50         }
 51         if(B.cnt1==1 and A.R){
 52             ++tmp.fr[min(2LL,B.cnt0+A.R)];
 53             tmp.fr[2]+=A.R-1;
 54         }
 55         tmp.L=(!A.cnt1?A.cnt0+B.L:A.L);tmp.R=(!B.cnt1?B.cnt0+A.R:B.R);
 56         tmp.cnt0=A.cnt0+B.cnt0;tmp.cnt1=A.cnt1+B.cnt1;tmp.s+=A.s+B.s;
 57         tmp.s+=A.dr[0][1]*(B.dl[1][0]+B.dl[0][0])+A.dr[1][0]*B.dl[0][1];
 58         tmp.s+=A.dr[0][0]*(B.dl[1][1]+B.dl[0][1])+A.dr[1][1]*B.dl[0][0];
 59         if(B.L)tmp.s+=(A.fr[1]+A.fr[2])*B.L+A.fr[0]*(B.L-1);
 60         if(A.R)tmp.s+=(B.fl[1]+B.fl[2])*A.R+B.fl[0]*(A.R-1);
 61         return tmp;
 62     }
 63     void pushup(node &tmp,int x){
 64         tmp.reset();
 65         if(x)tmp.s=tmp.fl[0]=tmp.fr[0]=tmp.dl[0][1]=tmp.dr[0][1]=tmp.cnt1=1;
 66         else tmp.dl[1][0]=tmp.dr[1][0]=tmp.L=tmp.R=tmp.cnt0=1;
 67     };
 68 public:
 69     void build(int l,int r,int rt=1){
 70         if(l==r){
 71             pushup(tree[rt],A[l]);
 72             return;
 73         }
 74         int m=(l+r)>>1;
 75         build(l,m,rt<<1);
 76         build(m+1,r,rt<<1|1);
 77         tree[rt]=comb(tree[rt<<1],tree[rt<<1|1]);
 78     }
 79     void update(int l,int r,int rt,int L){
 80         if(l==r){
 81             pushup(tree[rt],A[l]);
 82             return;
 83         }
 84         int m=(l+r)>>1;
 85         if(L<=m)update(l,m,rt<<1,L);
 86         else update(m+1,r,rt<<1|1,L);
 87         tree[rt]=comb(tree[rt<<1],tree[rt<<1|1]);
 88     }
 89     node query(int l,int r,int rt,int L,int R){
 90         if(L<=l and r<=R)return tree[rt];
 91         int m=(l+r)>>1;
 92         if(R<=m)return query(l,m,rt<<1,L,R);
 93         if(L>m)return query(m+1,r,rt<<1|1,L,R);
 94         return comb(query(l,m,rt<<1,L,m),query(m+1,r,rt<<1|1,m+1,R));
 95     }
 96 }segTree;
 97 void init(){
 98     scanf("%d",&n);
 99     range(i,1,n)scanf("%d",A+i);
100     segTree.build(1,n);
101     scanf("%d",&m);
102 }
103 void solve(){
104     while(m--){
105         scanf("%d%d",&op,&l);
106         if(op&1)A[l]^=1,segTree.update(1,n,1,l);
107         else{
108             scanf("%d",&r);
109             printf("%lld\n",1LL*(r-l+1)*(r-l+2)/2-segTree.query(1,n,1,l,r).s);
110         }
111     }
112 }
113 int main() {
114     init();
115     solve();
116     return 0;
117 }
View Code

 

转载于:https://www.cnblogs.com/Rhythm-/p/9455281.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2018年10个最佳项目管理工具及链接

要在任何业务中取得成功&#xff0c;对项目进行适当的管理非常重要。 项目管理是一系列活动&#xff0c;包括计划&#xff0c;执行&#xff0c;控制和完成项目。项目管理工具有助于简化此过程。这里是Best 10项目管理工具及其功能和下载链接的精选列表。1&#xff09;AsanaAsan…

Java 8 新特性之Stream API

1. 概述 1.1 简介 Java 8 中有两大最为重要的改革&#xff0c;第一个是 Lambda 表达式&#xff0c;另外一个则是 Stream API&#xff08;java.util.stream.*&#xff09;。 Stream 是 Java 8 中处理集合的关键抽象概念&#xff0c;它可以指定你希望对集合进行的操作&#xff0c…

[Python设计模式] 第17章 程序中的翻译官——适配器模式

github地址:https://github.com/cheesezh/python_design_patterns 适配器模式 适配器模式&#xff0c;将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作[DP]。 当系统的数据和行为都正确&#xff0c;但是接口…

Ubuntu中NS2安装详细教程

前言&#xff1a; NS2是指 Network Simulator version 2&#xff0c;NS&#xff08;Network Simulator&#xff09; 是一种针对网络技术的源代码公开的、免费的软件模拟平台&#xff0c;研究人员使用它可以很容易的进行网络技术的开发&#xff0c;而且发展到今天&#xff0c;它…

es6核心特性图

转载于:https://juejin.im/post/5c19e188e51d452db4753925

带你利用一句话完成转场动画

这篇文章主要给大家介绍了关于iOS如何利用一句话完成转场动画的相关资料&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面来一起学习学习吧前言本文介绍SS_AnimationTransition 的使用方法,利用…

14.vue路由脚手架

一.vue路由&#xff1a;https://router.vuejs.org/zh/ 1、定义 let router new VueRouter({mode:"history/hash",base:"基本路径" 加一些前缀 必须在history模式下有效linkActiveClass:"active", 范围选择linkExactActiveClass:"exact&qu…

工程师、产品经理、数据工程师是如何一起工作的?

做为一名工程师&#xff0c;免不了与产品经理打交道&#xff0c;如果公司大一些&#xff0c;数据量多一些&#xff0c;还会有数据工程师这个角色。今天会和你主要聊一聊在工作中&#xff0c;产品经理和数据工程师在哪些方面对我们工程师的帮助最大&#xff0c;以及我从他们身上…

linux-buff/cache过大导致内存不足-程序异常

2019独角兽企业重金招聘Python工程师标准>>> 问题描述 Linux内存使用量超过阈值&#xff0c;使得Java应用程序无可用内存&#xff0c;最终导致程序崩溃。即使在程序没有挂掉时把程序停掉&#xff0c;系统内存也不会被释放。 找原因的过程 这个问题已经困扰我好几个月…

Android 适配(一)

一、Android适配基础参数1.常见分辨率&#xff08;px&#xff09;oppx 2340x1080oppR15 2280x1080oppor11sp 2160*10801080*1920 (主流屏幕16&#xff1a;9)1080*216018:9 手机主流分辨率&#xff1a; 1080*2160高端 16:9 手机主流分辨率&#xff1a; 1080P (1080*1920) 或 2K …

Source Insight 创建工程(linux-2.6.22.6内核源码)

1. 软件设置 安装完Source Insight&#xff0c;需要对其进行设置添加对“.S”汇编文件的支持&#xff1a; 2. 新建linux-2.6.22.6工程 1&#xff09;选择工程存放的路径&#xff1a; 2&#xff09;下载linux-2.6.22.6内核源码&#xff0c;并解压。在Source Insight中 指定源码的…

课时20:内嵌函数和闭包

目录&#xff1a; 一、global关键字 二、内嵌函数 三、闭包 四、课时20课后习题及答案 ******************** 一、global关键字 ******************** 全局变量的作用域是整个模块&#xff08;整个代码段&#xff09;&#xff0c;也就是代码段内所有的函数内部都可以访问到全局…

从零开始学产品第六篇:更强大的测试,自动化测试和性能测试

本篇为【从零开始学产品】系列课第1章第5节欢迎到公众号菜单栏&#xff0c;获取产品经理课程更多资料 “测试就是拿点鼠标在电脑上瞎点&#xff0c;或者是用手机随便戳几下么&#xff1f;” “不&#xff0c;是有计划有意图的测试&#xff0c;比如说&#xff0c;边界测试&#…

Get 了滤镜、动画、AR 特效,速来炫出你的短视频开发特技!

在滤镜美颜、搞怪特效、炫酷场景等各种新奇玩法驱动下&#xff0c;短视频开始让人上瘾。 12 月 3 日&#xff0c;七牛云联合八大短视频特效平台共同推出了中国短视频开发者创意大赛&#xff08;China Short Video Contest&#xff09;&#xff0c;面向全国邀请广大开发者&#…

匿名函数、冒泡排序,二分法, 递归

匿名函数 lambda 匿名函数 格式 lambda 参数&#xff1a;返回值 函数名统一叫lambda&#xff0c;最多只能写一行普通的正常的函数 def func(n):return n * n lambda匿名函数写法 a lambda n : n**2 print(a(3)) 当有多个返回值时suiyi lambda x, y : (1, 2) # 笔试题 …

Redis源码剖析

Redis源码剖析和注释&#xff08;一&#xff09;---链表结构 Redis源码剖析和注释&#xff08;二&#xff09;--- 简单动态字符串 Redis源码剖析和注释&#xff08;三&#xff09;--- Redis 字典结构 Redis源码剖析和注释&#xff08;四&#xff09;--- 跳跃表(skiplist) Redis…

Android Activity生命周期

Android生命周期 Android的生命周期&#xff1a;onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy() 如下图所示&#xff1a; 1.当activity启动时系统会先调用onCreate(),然后调用onStart(),最后调用**onResume()**方法&#xff0…

date数据存入mysql_Date对象存入mysql数据库

java.sql.Date,java.sql.Time和java.sql.Timestamp三个都是java.util.Date的子类(包装类)。java.sql.Date是java.util.Date的子类&#xff0c;是一个包装了毫秒值的瘦包装器&#xff0c;允许 JDBC 将毫秒值标识为 SQL DATE 值。毫秒值表示自 1970 年 1 月 1 日 00:00:00 GMT 以…

盛严谨,严谨,再严谨。_评估员工调查的统计严谨性

盛严谨,严谨,再严谨。The human resources industry relies heavily on a wide range of assessments to support its functions. In fact, to ensure unbiased and fair hiring practices the US department of labor maintains a set of guidelines (Uniform Guidelines) to …

复权就是对股价和成交量进行权息修

* 所谓复权就是对股价和成交量进行权息修复,按照股票的实际涨跌绘制股价走势图, * 并把成交量调整为相同的股本口径。股票除权、除息之后&#xff0c;股价随之产生了变化&#xff0c; * 但实际成本并没有变化。 * 如&#xff1a;原来20元的股票&#xff0c;十送十之…