BZOJ5294 BJOI2018二进制(线段树)

时间:2022-01-05 07:23:55

  二进制数能被3整除相当于奇数、偶数位上1的个数模3同余。那么如果有偶数个1,一定存在重排方案使其合法;否则则要求至少有两个0且至少有3个1,这样可以给奇数位单独安排3个1。

  考虑线段树维护区间内的一堆东西,合并两节点时计算跨过区间中点的答案。可以对每个节点记录f[0/1][0/1][0/1][0/1/2]表示前/后缀,异或和为0/1,是否至少出现了两个1,出现了0/1/超过2个0。大力讨论即可。

  成功写了一晚上才不是因为要补十几面数学作业

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,a[N];
struct data{int f[][][][],l,r,sum;ll ans;
}tree[N<<];
data merge(data x,data y)
{
data p;memset(p.f,,sizeof(p.f));
p.l=x.l,p.r=y.r;
p.sum=x.sum+y.sum;
p.ans=x.ans+y.ans;
for (int i=;i<;i++)
{
int s1=,s2=;
for (int j=;j<;j++)
for (int k=;k<;k++)
s1+=x.f[][i][j][k],s2+=y.f[][i][j][k];
p.ans+=1ll*s1*s2;
}
for (int i=;i<;i++)
for (int j=-i;j<;j++)
for (int u=;u<;u++)
for (int v=;v<;v++)
if (u|v) p.ans+=1ll*x.f[][][u][i]*y.f[][][v][j]+1ll*x.f[][][u][i]*y.f[][][v][j];
int lone=x.sum,lzero=x.r-x.l+-lone,rone=y.sum,rzero=y.r-y.l+-rone;
for (int i=;i<;i++)
for (int j=;j<;j++)
for (int k=;k<;k++)
p.f[][i][j][k]+=x.f[][i][j][k],p.f[][i^(lone&)][lone+i>=||j][min(,lzero+k)]+=y.f[][i][j][k],
p.f[][i][j][k]+=y.f[][i][j][k],p.f[][i^(rone&)][rone+i>=||j][min(,rzero+k)]+=x.f[][i][j][k];
return p;
}
void newpoint(int k,int x)
{
memset(tree[k].f,,sizeof(tree[k].f));
tree[k].f[][x][][x^]=tree[k].f[][x][][x^]=;tree[k].ans=x^;tree[k].sum=x;
}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
if (l==r){newpoint(k,a[l]);return;}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
tree[k]=merge(tree[k<<],tree[k<<|]);
}
void modify(int k,int p,int x)
{
if (tree[k].l==tree[k].r) {newpoint(k,x);return;}
int mid=tree[k].l+tree[k].r>>;
if (p<=mid) modify(k<<,p,x);
else modify(k<<|,p,x);
tree[k]=merge(tree[k<<],tree[k<<|]);
}
data query(int k,int l,int r)
{
if (tree[k].l==l&&tree[k].r==r) return tree[k];
int mid=tree[k].l+tree[k].r>>;
if (r<=mid) return query(k<<,l,r);
else if (l>mid) return query(k<<|,l,r);
else return merge(query(k<<,l,mid),query(k<<|,mid+,r));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5294.in","r",stdin);
freopen("bzoj5294.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++) a[i]=read();
build(,,n);
m=read();
while (m--)
{
int op=read();
if (op==)
{
int x=read();
modify(,x,a[x]^=);
}
else
{
int l=read(),r=read();
printf(LL,query(,l,r).ans);
}
}
return ;
}

BZOJ5294 BJOI2018二进制(线段树)的更多相关文章

  1. BZOJ5294 BJOI2018 二进制 线段树

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

  2. 2019&period;02&period;12 bzoj5294&colon; &lbrack;Bjoi2018&rsqb;二进制(线段树)

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

  3. BZOJ5294 &lbrack;BJOI2018&rsqb; 二进制 【线段树】

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

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

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

  5. nowcoder 211E - 位运算?位运算! - &lbrack;二进制线段树&rsqb;&lbrack;与或线段树&rsqb;

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

  6. 【BZOJ5294】&lbrack;BJOI2018&rsqb;二进制(线段树)

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

  7. Bzoj5294&sol;洛谷P4428 &lbrack;Bjoi2018&rsqb;二进制(线段树)

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

  8. 洛谷P4428二进制 &lbrack;BJOI2018&rsqb; 线段树

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

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

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

随机推荐

  1. ghost 还原系统时,遇到error 10010,提示can not open image file

    昨天系统有点问题,在用Ghost还原系统时,一直提示10010错误,提示can not open image file 想着可能是备份文件的问题,从另一台电脑上重新拷过来一份,仍然不行,Ghost还是 ...

  2. JavaScript面向对象之类的继承

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. Kafka单机版安装&lpar;CentOS 7环境下&rpar;

    一.环境操作系统和软件版本介绍 1.环境操作系统为CentOS Linux release 7.2.1511 (Core) 可用cat /etc/redhat-release查询 2.软件版本 Kaf ...

  4. HDU-1701-ACMer

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1701 解题: 好久没做题,好久没写解题思路了,连简答题都不会做了,下午的月赛挂了,我悲剧了,在此发牢骚 ...

  5. powerdesigner添加mysql的字符集ENGINE和DEFAULT CHARACTER SET

    工具栏->database->edit current DBMS 然后,选中:MYSQL50::Script\Objects\Table\Options 在options末尾添加: ENG ...

  6. ViewParent 和 ViewManager

    ViewGroup 继承了 View  实现了两个接口  ViewParent 和 ViewManager 接口 ViewParent:定义了成为一个View的parent的一些“职能”,当paren ...

  7. 执行update语句mysql5&period;6报错ERROR 1292 &lpar;22007&rpar;&colon; Truncated incorrect DOUBLE value&colon; &&num;39&semi;糖糖的坤大叔&&num;39&semi;

    执行修改语句update tbl_user_details set nickname=CONCAT("用户",yunva_id) where nickname = yunva_id ...

  8. ruby的循环使用及区别(for、each等)

    ruby的循环有以下几种: times方法 for语句 while语句 until语句(与while相反) each方法(与for极度相似,在ruby内部,for语句是用each实现的) loop方法 ...

  9. html实现鼠标悬停变成手型实现方式

    1.采用a标签实现的方式 <a href="javascript:void()">内容</a> 2.采用CSS实现的方式 // 变手形 oElement.s ...

  10. 求职之路共分享——亲身面试题(一) 1&sol;三层与MVC区别

    转自http://www.cnblogs.com/ndxsdhy/archive/2011/08/04/2127908.html 觉得这篇文章挺容易理解的, http://www.cnblogs.co ...