异或序列 [set优化DP]
\(\mathcal{Description}\)
有一个长度为 \(n\)的自然数序列 \(a\),要求将这个序列分成至少 \(m\) 个连续子段
每个子段的价值为该子段的所有数的按位异或
要使所有子段的价值按位与的结果最大,输出这个最大值
\(T\)组询问
\(T\leq 10,n,m\leq 1000,a_i\leq 2^{30}\)
\(\mathcal{Solution}\)
实际上数据范围可开大很多
我们贪心的一位一位的确定最终答案,即看当前考虑的位能否为\(1\)
记\(s_i\)表示前\(i\)个数的异或和,\(\bigoplus\)表示异或
设当前考虑到了第\(b\)位
令\(res=ans|(1<<b)\)
一段区间\([j+1,i]\)如果是一个合法的区间,可以得到
\(\left(s_i\bigoplus s_j\right)\&res=res\)
于是我们得到了一个\(n^2log\)的\(DP\)方程
\(f_i=max{f_i,f_j+1}\)其中\(\left(s_i\bigoplus s_j\right)=res\)
枚举位是\(log\)的,这样就可以\(AC\)此题了
实际这个\(DP\)可以进一步优化
\(\left(s_i\bigoplus s_j\right)\&res=res\)可以推出
\(\left(s_i \& res\right)\bigoplus \left(s_j\& res\right)=res\)
\(\Rightarrow s_i \& res=\left(s_j\& res\right)\bigoplus res\)
即要将\(s_i\)到\(s_j\)这段作为一个子段必须满足上面的条件
因为题目是至少\(m\)段,所以分的越多越好
则我们可以考虑完\(s_i\)的最优答案后将\(s_i\bigoplus res\)作为第一关键字存进\(set\)
\(f_i=find(s_i\bigoplus res)\)
这样一次转移就是\(log\)的
复杂度为\(nlog^2\)
\(\mathcal{Code}\)
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年10月26日 星期六 09时18分19秒
*******************************/
#include <cstdio>
#include <fstream>
#include <cstring>
#include <set>
#define mp make_pair
using namespace std;
const int maxn = 2003;
//{{{cin
struct IO{
template<typename T>
IO & operator>>(T&res){
res=0;
bool flag=false;
char ch;
while((ch=getchar())>'9'||ch<'0') flag|=ch=='-';
while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
if (flag) res=~res+1;
return *this;
}
}cin;
//}}}
int n,m,T,ans;
int a[maxn],s[maxn];
set < pair<int,int> > v;
set < pair<int,int> > :: iterator it,nx;
//{{{solve
void solve (int x)
{
int res=ans|(1<<x);
bool flag;
v.clear();
for (int i=1;i<=n;++i){
int val=s[i]&res;
v.insert(mp(val,0));
nx=it=v.lower_bound(mp(val,0));
++nx;
while (nx!=v.end()&&nx->first==val){
v.erase(it);
it=nx,++nx;
}
if (it->second==0){
if (val==res){
v.insert(mp(val^res,1));
if (i==n) flag=it->second+1>=m;
}
}
else{
v.insert(mp(val^res,(it->second)+1));
if (i==n) flag=it->second+1>=m;
}
}
if (flag) ans=res;
}
//}}}
int main()
{
cin>>T;
while (T--){
cin>>n>>m;
ans=0;
for (int i=1;i<=n;++i){
cin>>a[i];
s[i]=s[i-1]^a[i];
}
for (int i=29;~i;--i) solve(i);
printf("%d\n",ans);
}
return 0;
}
如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧
异或序列 [set优化DP]的更多相关文章
- CF 1150 D Three Religions——序列自动机优化DP
题目:http://codeforces.com/contest/1150/problem/D 老是想着枚举当前在给定字符串的哪个位置,以此来转移. 所以想对三个串分别建 trie 树,然后求出三个t ...
- 2018.09.29 bzoj3675: [Apio2014]序列分割(斜率优化dp)
传送门 斜率优化dp经典题目. 首先需要证明只要选择的K个断点是相同的,那么得到的答案也是相同的. 根据分治的思想,我们只需要证明有两个断点时成立,就能推出K个断点时成立. 我们设两个断点分成的三段连 ...
- 【bzoj3675】[Apio2014]序列分割 斜率优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列 ...
- 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)
点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...
- BZOJ 3675 APIO2014 序列切割 斜率优化DP
题意:链接 方法:斜率优化DP 解析:这题BZ的数据我也是跪了,特意去网上找到当年的数据后面二十个最大的点都过了.就是过不了BZ. 看到这道题自己第一发DP是这么推得: 设f[i][j]是第j次分第i ...
- 洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP
洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...
- 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点
容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...
- 最长子序列(线性DP)学习笔记
子序列和子串不一样.子串要求必须连续,而子序列不需要连续. 比如说\(\{a_1,a_2\dots a_n\}\),他的子串就是\(\{a_i,a_{i+1},\dots, a_j|1\leq i\l ...
- HDU 2993 MAX Average Problem(斜率优化DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给定一个长度为n(最长为10^5)的正整数序列,求出连续的最短为k的子序列平均值的最大 ...
随机推荐
- Zookeeper循环注册监听器
Zookeeper中的监听器只执行一次,需要在watcher类中重写process方法,以达到重复注册监听器的效果 /** * 连接zk服务器 * */ public static void conn ...
- shell 输出文件各行的长度
test.sh #!/bin/bash string="hello,shell,split,test" array=(${string//,/ }) for var in ${ar ...
- 欧拉法求解常微分方程(c++)
#include<iostream> #include<iomanip> using namespace std; int main() { double x, y, h; ...
- Kafka(三)High Availability 高可用
参考文档: http://www.jasongj.com/2015/04/24/KafkaColumn2/#ACK%E5%89%8D%E9%9C%80%E8%A6%81%E4%BF%9D%E8%AF% ...
- 第08组 Beta冲刺(3/4)
队名 八组评分了吗 组长博客链接(2分) 组员1李昕晖(组长) 过去两天完成了哪些任务 文字/口头描述 了解各个小组的进度与难以攻破的地方,晚上安排开会,安排新的冲刺任务. 重新分配小组及个人任务. ...
- git 下载指定tag版本的源码<转>
git clone --branch x.x.x https://xxx.xxx.com/xxx/xxx.git 原文地址:https://blog.csdn.net/weixin_30617561/ ...
- 源码编译Redis Desktop Manager ---(转载)
精美文章转载: 版权声明:本文作者为「Kany.Wang」,本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议.转载请注明出处!原文链接:https://kany.me/20 ...
- Solidity开发注意
pragma版本:1.版本要高于0.4.24才可以编译:2.高于0.5的版本则不可编译:3.第三位的版本号可以变,留出来用做bug可以修复(如0.4.1的编译器有bug,可在0.4.2修复,现有合约不 ...
- jQuery-webcam使用
基本页面 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta ...
- Ajax验证
import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactor ...