中国石油大学(华东)暑期集训--二进制(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,一经查实,立即删除!

相关文章

Java 8 新特性之Stream API

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

Ubuntu中NS2安装详细教程

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

14.vue路由脚手架

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

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;也就是代码段内所有的函数内部都可以访问到全局…

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

盛严谨,严谨,再严谨。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 …

开根号的笔算算法图解_一个数的开根号怎么计算

一个数的开根号怎么计算2020-11-08 15:46:47文/钟诗贺带根号的式子可以直接进行开平方的运算。一些特殊的根号运算有;√2≈1.414、1/2-√3≈0.5-1.732≈-1.232、2√5≈22.236≈4.236、√7-√6≈2.646-2.449≈0.197。开平方的笔算方法1&#xff0e;将被开方数的整数部分从个位起…

arima 预测模型_预测未来:学习使用Arima模型进行预测

arima 预测模型XTS对象 (XTS Objects) If you’re not using XTS objects to perform your forecasting in R, then you are likely missing out! The major benefits that we’ll explore throughout are that these objects are a lot easier to work with when it comes to …

bigquery_在BigQuery中链接多个SQL查询

bigqueryBigquery is a fantastic tool! It lets you do really powerful analytics works all using SQL like syntax.Bigquery是一个很棒的工具&#xff01; 它使您能够使用像语法一样SQL来进行真正强大的分析工作。 But it lacks chaining the SQL queries. We cannot run …

大理石在哪儿 (Where is the Marble?,UVa 10474)

题目描述&#xff1a;算法竞赛入门经典例题5-1 1 #include <iostream>2 #include <algorithm>3 using namespace std;4 int maxn 10000 ;5 int main()6 {7 int n,q,a[maxn] ,k0;8 while(scanf("%d%d",&n,&q)2 && n &&q…

mysql 迁移到tidb_通过从MySQL迁移到TiDB来水平扩展Hive Metastore数据库

mysql 迁移到tidbIndustry: Knowledge Sharing行业&#xff1a;知识共享 Author: Mengyu Hu (Platform Engineer at Zhihu)作者&#xff1a;胡梦瑜(Zhhu的平台工程师) Zhihu which means “Do you know?” in classical Chinese, is the Quora of China: a question-and-ans…

XCode、Objective-C、Cocoa 说的是几样东西

大部分有一点其他平台开发基础的初学者看到XCode&#xff0c;第一感想是磨拳擦掌&#xff0c;看到 Interface Builder之后&#xff0c;第一感想是跃跃欲试&#xff0c;而看到Objective-C的语法&#xff0c;第一感想就变成就望而却步了。好吧&#xff0c;我是在说我自己。 如果…

递归函数基例和链条_链条和叉子

递归函数基例和链条因果推论 (Causal Inference) This is the fifth post on the series we work our way through “Causal Inference In Statistics” a nice Primer co-authored by Judea Pearl himself.这是本系列的第五篇文章&#xff0c;我们通过“因果统计推断”一书进行…

java lock 信号_java各种锁(ReentrantLock,Semaphore,CountDownLatch)的实现原理

先放结论&#xff1a;主要是实现AbstractQueuedSynchronizer中进入和退出函数&#xff0c;控制不同的进入和退出条件&#xff0c;实现适用于各种场景下的锁。JAVA中对于线程的同步提供了多种锁机制&#xff0c;比较著名的有可重入锁ReentrantLock&#xff0c;信号量机制Semapho…

Intent.ACTION_MAIN

1 Intent.ACTION_MAIN String: android.intent.action.MAIN 标识Activity为一个程序的开始。比较常用。 Input:nothing Output:nothing 例如&#xff1a; 1 <activity android:name".Main"android:label"string/app_name">2 <intent-filter…

足球预测_预测足球热

足球预测By Aditya Pethe通过阿蒂亚皮特(Aditya Pethe) From September to January every year, football takes over America. Games dominate TV Sunday and Monday nights, and my brother tears his hair out each week over his consistently underperforming fantasy te…

C#的特性Attribute

一、什么是特性 特性是用于在运行时传递程序中各种元素&#xff08;比如类、方法、结构、枚举、组件等&#xff09;的行为信息的声明性标签&#xff0c;这个标签可以有多个。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号&am…

python3中朴素贝叶斯_贝叶斯统计:Python中从零开始的都会都市

python3中朴素贝叶斯你在这里 (You are here) If you’re reading this, odds are: (1) you’re interested in bayesian statistics but (2) you have no idea how Markov Chain Monte Carlo (MCMC) sampling methods work, and (3) you realize that all but the simplest, t…