BJOI的题目感觉有点难写

题目分析:

  首先推一波结论。接下来的一切都在模3意义下

  现在我们将二进制位重组,不难发现的是2^0≡1,2^1≡2,2^2≡1,2^3≡2....所以我们考虑这样的式子

  2*a+b≡0 mod 3

  其中a+b为某个区间的1的个数,令它为tot。试着带几个值看看。

  2*1+1+3k≡0;

  2*2+2+3k≡0;

  2*3+0+3k≡0;

  可以发现a和b实际上在任何时候都有a≡b。也就是说a≡tot-a。

  这等价于2*a≡tot。对于每一个tot,我们把它对应最好的a写出来,会发现当(tot%6)%2==0的时候,这个区间在任何时候都满足它可以通过重组被3整除。

  否则它的这个区间至少需要2个0,这是因为你重组之后结果是余1,这时候你需要将一个奇数位换到一个偶数位,所以你需要2个0来新构建一个偶数位。

  这里需要注意,1的情况是特殊的,它无论如何也不能被3整除。

  接着我们得到了结论,当(tot%6)%2==0或者(tot%6)%2==1且该区间中至少有2个0,那么该区间可以通过重组被3整除。

  考虑问题的反面,有多少个区间不可以被3整除,这就等价于找(tot%6)%2==1且该区间只有1个0或没有0的区间的个数,这个问题是线段树的一个基本操作。

  该区间的所有子区间的个数等于一个等差数列。线段树通过维护第一个1,第二个1,第一个0,第二个0,最后一个0,倒数第二个0,最后一个1,倒数第二个1的位置和不满足的子区间数。可以很好的合并。

  时间复杂度O(nlogn),由于维护的信息比较多,常数很大。

代码:

  

#include<bits/stdc++.h>
using namespace std; const int maxn = ; struct node{
long long hh; //1,3,5
int l1,l2,r1,r2;
int p1,p2,q1,q2;
}T[maxn<<]; int wh[maxn];
int n,q;
node ans;//int rl,rr; int dm[],md[]; void get_height(int l,int r,int *d,int now = ){
if(now == ) for(int i=;i<;i++) d[i]=;
if(l > r) return;
int len = r-l+;
for(int i=;i<;i++){
d[(i+l-)%] += (len/)+(len%>=i);
if(i == )d[(i+l-)%]--;
}
} node merge(node a,node b,int l,int mid,int r){
if(l > mid) return b;
node z; z.hh = a.hh+b.hh;
z.l1 = z.l2 = z.r1 = z.r2 = z.p1 = z.p2 =z.q1 = z.q2 = ; int mem = mid-a.r1,nen = b.l2-mid-;
int lem = mid-a.r2,len = b.l1-mid-; if(b.l2==)nen = r-mid; if(a.r1==)mem=mid-l+;
if(b.l1 == )len = r-mid; if(a.r2==)lem=mid-l+;
get_height(,mem,dm);get_height(,len,md);
get_height(+len,nen-,md,);
if(b.l1) md[len%]++;
for(int i=;i<;i++){
z.hh += 1ll*dm[i]*md[(-i)%];
z.hh += 1ll*dm[i]*md[(-i)%];
z.hh += 1ll*dm[i]*md[(-i)%];
} get_height(mem+,lem-,dm);get_height(,len,md);
if(a.r1) dm[mem%]++;
for(int i=;i<;i++){
z.hh += 1ll*dm[i]*md[(-i)%];
z.hh += 1ll*dm[i]*md[(-i)%];
z.hh += 1ll*dm[i]*md[(-i)%];
} lem = mid-a.q2-(mid-a.q1),len = b.p1-mid-;
if(a.q2 == )lem = (a.q1==?:mid-l+-(mid-a.q1));
if(b.p1 == )len = r-mid;
z.hh += 1ll*lem*len;
if(a.q1==mid&&b.l1==mid+)z.hh--; lem = mid-a.q1,len = b.p2-mid--(b.p1-mid-);
if(a.q1 == )lem = mid-l+;
if(b.p2 == )len = (b.p1==?:r-mid-(b.p1-mid-));
z.hh += 1ll*lem*len;
if(a.r1==mid&&b.p1==mid+)z.hh--; int num = ;
if(a.l1) dm[++num]=a.l1; if(a.l2) dm[++num]=a.l2;
if(b.l1) dm[++num]=b.l1; if(b.l2) dm[++num]=b.l2;
if(num>=) z.l1 = dm[];
if(num>=) z.l2 = dm[]; num = ;
if(b.r1) dm[++num]=b.r1; if(b.r2) dm[++num]=b.r2;
if(a.r1) dm[++num]=a.r1; if(a.r2) dm[++num]=a.r2;
if(num>=) z.r1 = dm[];
if(num>=) z.r2 = dm[]; num = ;
if(a.p1) dm[++num]=a.p1; if(a.p2) dm[++num]=a.p2;
if(b.p1) dm[++num]=b.p1; if(b.p2) dm[++num]=b.p2;
if(num>=) z.p1 = dm[];
if(num>=) z.p2 = dm[]; num = ;
if(b.q1) dm[++num]=b.q1; if(b.q2) dm[++num]=b.q2;
if(a.q1) dm[++num]=a.q1; if(a.q2) dm[++num]=a.q2;
if(num>=) z.q1 = dm[];
if(num>=) z.q2 = dm[];
return z;
} void init(int now,int pla){
if(wh[pla] == ){
T[now].hh = ;
T[now].l1 = T[now].r1 = pla;
T[now].l2 = T[now].r2 = ;
T[now].q1 = T[now].q2 = T[now].p1 = T[now].p2 = ;
}else{
T[now].hh=;
T[now].p1 = T[now].q1 = pla; T[now].hh=;
T[now].p2 = T[now].q2 = ;
T[now].l1 = T[now].r1 = T[now].l2 = T[now].r2 = ;
}
} void Modify(int now,int l,int r,int pla){
if(l == r){init(now,pla);return;}
int mid = (l+r)/;
if(mid >= pla) Modify(now<<,l,mid,pla);
else Modify(now<<|,mid+,r,pla);
T[now] = merge(T[now<<],T[now<<|],l,mid,r);
} void Query(int now,int tl,int tr,int l,int r){
if(tl >= l && tr <= r){ans = merge(ans,T[now],l,tl-,tr);return;}
if(tr < l || tl > r) return;
int mid = (tl+tr)/;
Query(now<<,tl,mid,l,r);
Query(now<<|,mid+,tr,l,r);
} void build_tree(int now,int l,int r){
if(l == r){init(now,l);return;}
int mid = (l+r)/;
build_tree(now<<,l,mid);
build_tree(now<<|,mid+,r);
T[now] = merge(T[now<<],T[now<<|],l,mid,r);
} void read(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&wh[i]);
build_tree(,,n);
} void work(){
scanf("%d",&q);
for(int i=;i<=q;i++){
int x; scanf("%d",&x);
if(x == ){
int p; scanf("%d",&p);
wh[p] ^= ;
Modify(,,n,p);
}else{
int l,r; scanf("%d%d",&l,&r);
Query(,,n,l,r);
long long res = 1ll*(+r-l)*(r-l+)/;
printf("%lld\n",res-ans.hh);
}
}
} int main(){
read();
work();
return ;
}

BZOJ5294 [BJOI2018] 二进制 【线段树】的更多相关文章

  1. BZOJ5294 BJOI2018 二进制 线段树

    传送门 因为每一位\(\mod 3\)的值为\(1,2,1,2,...\),也就相当于\(1,-1,1,-1,...\) 所以当某个区间的\(1\)的个数为偶数的时候,一定是可行的,只要把这若干个\( ...

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

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

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

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

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

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

  5. nowcoder 211E - 位运算?位运算! - [二进制线段树][与或线段树]

    题目链接:https://www.nowcoder.com/acm/contest/211/E 题目描述 请实现一个数据结构支持以下操作:区间循环左右移,区间与,区间或,区间求和. 输入描述: 第一行 ...

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

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

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

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

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

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

  9. POJ 2777 Count Color(线段树染色,二进制优化)

    Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42940   Accepted: 13011 Des ...

随机推荐

  1. async源码学习 - 全部源码

    因为工作需要,可能我离前端走远了,偏node方向了.所以异步编程的需求很多,于是乎,不得不带着学习async了. 我有个习惯,用别人的东西之前,喜欢稍微搞明白点,so就带着看看其源码. github: ...

  2. oracle 把查询结果插入到表中几种方式

    转载:Oracle中把一个查询结果插入到一张表中 以下是信息留存: 一.Oracle数据库中,把一张表的查询结果直接生成并导入一张新表中. 例如:现有只有A表,查询A表,并且把结果导入B表中.使用如下 ...

  3. Luogu3350 ZJOI2016 旅行者 最短路、分治

    传送门 题意:给出一个$N \times M$的网格图,边有边权,$Q$组询问,每组询问$(x_1,y_1)$到$(x_2,y_2)$的最短路.$N \times M \leq 2 \times 10 ...

  4. Luogu P1129 [ZJOI2007]矩阵游戏

    题目意思还是比较直观的,而且这个建模的套路也很明显. 我们首先考虑从主对角线可以转移到哪些状态. 由于每一次操作都不会把同一行(列)的黑色方块分开.因此我们发现: 只要找出\(n\)个黑色棋子,让它们 ...

  5. openMP多线程编程

    OpenMP(Open Muti-Processing) OpenMP缺点: 1:作为高层抽象,OpenMp并不适合需要复杂的线程间同步和互斥的场合: 2:另一个缺点是不能在非共享内存系统(如计算机集 ...

  6. Jmeter(三十一)_数据驱动,业务关联

    这种数据驱动的本质是:将测试的case,参数,url,预期结果,存储于本地excel中.运行脚本时,从文件中获取预期结果,将实际结果与预期结果比较,将实际结果,比较结果,响应状态码回写excel. 一 ...

  7. Swarm基于多主机容器网络 - overlay networks 梳理

    前面介绍了Docker管理工具-Swarm部署记录,下面重点说下Swarm基于多主机容器通信的覆盖网络 在Docker版本1.12之后swarm模式原生支持覆盖网络(overlay networks) ...

  8. Peer Programming Project: 4 Elevators Scheduler 附加题 157 165

    1.改进电梯调度的interface 设计, 让它更好地反映现实, 更能让学生练习算法, 更好地实现信息隐藏和信息共享. 每个电梯增加目标楼层数组,这样可以更好地进行任务的分配,在我们的电梯中,这个数 ...

  9. Bing词典案例分析

    一.调研评测 Bug 1 : 当鼠标移动到可点击的地方的时候,光标的样子并没有变成手指状而是插入符号状.这影响了用户对按钮是否可用的判断,也会让用户在一定程度上不适应,不利于软件的长期发展. Bug  ...

  10. 使用github的感想

    github的仓库链接:https://github.com/liyan941016/test  github是一个基于git的代码托管平台,要想使用github第一步就要注册账户,然后要创建一个仓库 ...