题目链接

题面

题目描述

\(Mas\)完成了一天的工作,走在回家的路上,看着路边的景色,他想起来自己的童年。

许许多多的记忆交错,丝丝缕缕的牵扯着\(Mas\)。

在回忆的深处,\(Mas\)想起来了一个常常在幼儿园玩的游戏。

有\(n\)个小朋友一起排成一排,然后小朋友们会一起开始跳舞。

聪明的\(Mas\)发现,每个小朋友都有自己的高兴程度,对于第\(i\)个小朋友,他的高兴程度是\(ai\)。

当一排高兴程度分别为\(b_1,b_2,…,b_k\)的\(k\)个小朋友跳舞的时候,他们会产生\(b1 \otimes b2 \otimes ⋯\otimes bk\)的愉悦值。

但是\(Mas\)觉得不够尽兴,于是他决定让小朋友们从某个位置分开,让原本一排的队伍分成两排,从而使两排新队伍的愉悦值加起来最大,当然,是有可能不分成两排的。

具体的,对于一排kk个小朋友,他们的高兴程度分别是\(b_1,b_2,…,b_k\),\(Mas\)会找到位置\(i\in [0,k),使得(b1\otimes ⋯\otimes bi)+(bi+1\otimes ⋯\otimes bk)\)最大。

回想起这个游戏的\(Mas\)决定再来玩一下这个游戏,于是他想起来了某一天排成一排的\(n\)个小朋友的高兴程度\(a1,a2,…,an\)对于\(i=1..n\),\(Mas\)希望求出前\(i\)个小朋友排成的队伍中通过拆分成两个队伍能够得到的最大愉悦值的和是多少。

输入

第一行一个正整数\(n\)表示小朋友的数量。

第二行\(n\)个整数,表示\(a_{1..n}\)。

输出

一行\(n\)个整数表示答案。

思路

读完拉么长的题面。发现他其实就是对于每个位置要求这个东西

\[max\{(S_i \otimes S_j)+ S_j\}
\]

其中\(S_i\)表示前\(i\)个元素的异或和。

然后根据\(a+b = a\otimes b + (a \& b) \times 2\)

这个证明的话很显然:因为异或相当于不进位的加法。用\(\&\)可以求出需要进位的位置。然后乘二在相加就可以啦。

这样我们就可以把要求的式子变成这个样子

\[max\{S_i \otimes S_j \otimes S_j + (S_i \otimes S_j \& S_j) \times 2\}
\]

\[=max\{S_i + (S_i \otimes S_j \& S_j) \times 2\}
\]

因为\(S_i\)是确定的,只要让\(S_i \otimes S_j \& S_j\)最大就行了。

然后我们按位思考。对于二进制下的第\(k\)位。如果\(S_i\)的这一位为\(1\),那么不管\(S_j\)这一位是什么,肯定都无法将答案的这一位变成\(1\)。

所以我们就想要让\(S_i\)为\(0\)的那些位置尽可能变成\(1\)。

对于每个\(S_j\),我们将他和他的子集标记一下。然后贪心的从高位到低位将\(S_i\)为\(0\)的位置变为\(1\).

并且查看当前的答案是不是之前标记过。

具体看代码吧

代码

/*
* @Author: wxyww
* @Date: 2019-03-30 08:10:10
* @Last Modified time: 2019-03-31 08:31:43
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 2000000 + 100;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int s[N];
bool vis[N];
void ins(int x) {
if(vis[x]) return;
vis[x] = true;
for(int i = 0;i <= 20;++i) {
if((x >> i) & 1) ins(x - (1 << i));
}
}
int solve(int x) {
int ret = 0;
int k = x ^ ((1 << 21) - 1);
for(int i = 20;i >= 0;--i)
if(((k >> i) & 1) && vis[(ret + (1 << i))])
ret += (1 << i);
return ret;
}
int main() {
int n = read();
for(int i = 1;i <= n;++i) s[i] = s[i - 1] ^ read(); vis[0] = true; for(int i = 1;i <= n;++i) {
printf("%d ",solve(s[i]) * 2 + s[i]);
ins(s[i]);
} return 0;
}

noi.ac309 Mas的童年的更多相关文章

  1. 【noi.ac】#309. Mas的童年

    #309. Mas的童年 链接 分析: 求$max \{sj + (s_i \oplus s_j)\}$ 因为$a + b = a \oplus b + (a \& b) \times 2$ ...

  2. noi.ac#309 Mas的童年(子集乱搞)

    题意 题目链接 Sol 记\(s_i\)表示前\(i\)个数的前缀异或和,我们每次相当于要找一个\(j\)满足\(0 < j < i\)且\((s_i \oplus s_j) + s_j\ ...

  3. Noi.ac #309. Mas的童年(贪心)

    /* 用所谓的加法拆分操作得到 x + y = (x ^ y) + 2 * (x & y) 那么我们这两段异或相当于前缀和 + 2 * 分段使左右两块&最大 记当前前缀异或和为S, 那 ...

  4. [NOI.AC省选模拟赛3.30] Mas的童年 [二进制乱搞]

    题面 传送门 思路 这题其实蛮好想的......就是我考试的时候zz了,一直没有想到标记过的可以不再标记,总复杂度是$O(n)$ 首先我们求个前缀和,那么$ans_i=max(pre[j]+pre[i ...

  5. # NOI.AC省选赛 第五场T1 子集,与&最大值

    NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...

  6. NOI2019 SX 模拟赛 no.5

    Mas 的童年 题目描述:不知道传送门有没有用? 反正就是对于每个前缀序列求一个断点,使得断点左右两个区间的 分别的异或和 的和最大 分析 jzoj 原题? 但是我 TM 代码没存账号也过期了啊! 然 ...

  7. NOI2019省选模拟赛 第五场

    爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...

  8. 从一道NOI练习题说递推和递归

    一.递推: 所谓递推,简单理解就是推导数列的通项公式.先举一个简单的例子(另一个NOI练习题,但不是这次要解的问题): 楼梯有n(100 > n > 0)阶台阶,上楼时可以一步上1阶,也可 ...

  9. NOI 动态规划题集

    noi 1996 登山 noi 8780 拦截导弹 noi 4977 怪盗基德的滑翔翼 noi 6045 开餐馆 noi 2718 移动路线 noi 2728 摘花生 noi 2985 数字组合 no ...

随机推荐

  1. Activiti(一) activiti数据库表说明

    activiti介绍: activiti是一个业务流程管理(BPM)框架.它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源的.灵活的.易扩展的可执行流程语言框架.开发人员可以通过插件直接绘画出 ...

  2. 解决IE6-IE7下li上下间距变大问题

    在IE6/7下li会向下产生大约2px的外边距 解决方法:li{vertical-align:top;}或者       li{vertical-align:bottom;} 解决问题!

  3. JS 的继承

    1:原生链:prototype 儿子能够继承父亲的属性,也可以觉得遗传基因不好自己改属性,(但是不能改变老爸的属性). 看例子:             function farther(){     ...

  4. Golang学习笔记(一)

    这个系列学习文章是对ASTAXIE大神的GoWeb编程的读书笔记. 1. 关于GOPATH $GOPATH 是系统中重要的环境变量,他不是Go的安装目录. 假如我们将GOPATH设置在这里: /hom ...

  5. 二、Snapman多人协作电子表格之——软件下载安装与配置

    Snapman多人协作电子表格是一个即时工作系统. 一.软件下载地址 Snapman下载的官网地址:http://www.snapman.xyz 在官网下载Snapman主程序安装: snapman_ ...

  6. Mac电脑 怎么导出安卓手机的相册

    1.mac上下载一个HandShaker 2.把电脑和手机设置在同一个wifi下 3.安卓手机上下载一个HandShaker 参考:https://zhidao.baidu.com/question/ ...

  7. Python笔记-IO编程

    IO在计算机中是指input和output(数据输入与输出),涉及到数据交换(磁盘.网络)的地方就需要IO接口. 输入流input stream是指数据从外面(磁盘.网络服务器)流入内存:输出流out ...

  8. 【English】四、Y结尾名词变复数

    一.辅音字母+y结尾的名词,将y改变为i,再加-es. 读音变化:加读[z]. 例: candy→candies; daisy→daisies; fairy→fairies; lady→ladies; ...

  9. python高级(4)—— 虚拟环境安装使用

    虚拟环境 什么是虚拟环境 对电脑稍微有点常识的朋友相信都玩过,比如VMware,virtualbox,或者你用电脑端的模拟器玩手机端的游戏也是一样,其实就是一个假的空间,在Python这里,虚拟环境就 ...

  10. Postgresql数据库部署之:Postgresql 存在session 会话不能删除数据库

    SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='数据库名' AND pid<>pg_backen ...