题目链接

题面

题目描述

\(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. IntelliJ IDEA如何激活?

    本文使用的IDEA的版本是:14.0.3 下载IDEA授权服务器(下载地址见最后),并解压,打开解压后的IntelliJIDEALicenseServer目录,可以看到如下的两个文件: Intelli ...

  2. Ext.isNumber与Ext.isNumeric

    Ext.isNumber: Ext.isNumber(1) true Ext.isNumber(new Number(1)) false Ext.isNumber("1") fal ...

  3. element表格添加查看操作

    表格代码:黄色部分关键代码 首先看效果: <el-table :data="tableData" border height="480" style=&q ...

  4. OpenCL洗牌函数shuffle

    在OpenCL中,经常会碰到会对向量的多个分量进行交叉运算的情况,比如 float4 d4; //input float scale; //input float2 mix_0 = mix((floa ...

  5. 设计模式系列之装饰模式(Decorator Pattern)

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.这种模式创建了一个装饰类,用来包装原 ...

  6. thinkphp5.1验证器场景验证中传参的方法。

    一个场景:用户保存自己的昵称,如果已经有其他用户用了这个昵称则不允许保存,但是要排除当前用户自己,因为如果用户未作修改,新昵称和老昵称一样,是可以保存的. 因为昵称定义了唯一规则: 'name' =& ...

  7. 一个ELK日志检索实施案例

    figure:first-child { margin-top: -20px; } #write ol, #write ul { position: relative; } img { max-wid ...

  8. 如何在element-UI 组件的change事件中传递自定义参数

    以select为例,如果select写在循环里,触发change事件时可能不只需要传递被选中项的值,还要传递index过去,来改变同一循环中的其他标签的状态. 下面这样写是无效的: @change=& ...

  9. Linux Docker的部署

    1.安装 $ yum -y install docker 2.启动docker服务 $ systemctl start docker 3.设置开启自启 $ systemctl enable docke ...

  10. Core官方DI剖析(1)--ServiceProvider类和ServiceCollection类

    前段时间看了蒋老师的Core文章,对于DI那一块感觉挺有意思,然后就看了一下Core官方DI的源码,这也算是第一个看得懂大部分源码的框架,虽然官方DI相对来说特别简单, 官方DI相对于其它框架(例如 ...