【HDU - 5845】Best Division(xor-trie、01字典树、dp)
BUPT2017 wintertraining(15) #7E
题意
把数组A划分为k个区间,每个区间不超过L长度,每一个区间异或和之和为S。现在求:S不超过X,区间个数的最大值。
且A是这样给你的:A[1], P, Q。A[i]=(A[i-1]*P+Q)%M。M为\(2^{28}\)。
题解
容易想到dp, dp[i] :前 i 个数最多划分多少个区间。s[i]为前缀异或和。
dp[i]=max(dp[j]+1),i-L<j<i,且s[j]^s[i]\(\le\) x。
dp[n]就是答案。
但是这样是\(O(n^2)\)。
用 异或字典树 优化为\(O(nlogA)\)。
字典树来维护s[i],总共N个数,最多28位,所以28*N个节点。
要找 j 满足s[j]异或s[i]不超过x的最大的dp[j]+1。我们沿着字典树一位位找,如果x这一位是0,那么s[j]这一位肯定是和s[i]相同,异或起来才不超过x。如果x这一位是1,那么s[j]这一位可以和s[i]相同,直接取这个节点的最大值;也可以是与s[i]不同,然后继续走。
因为长度不超过L,所以每次处理到第i个,要删去第i-L-1个。
因为一个异或值可能出现多次,所以记录出现次数,删去时减少一次出现次数,次数为0时将对应的值设为-1。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#define M 268435456
#define N 100005
using namespace std;
int dp[N], a[N];
struct Trie{
int ch[N*28][2];
int val[N*28];//异或到当前位置不超过x的最多区间数
int cnt[N*28];//出现次数
int size;
void init(){
size=0;
memset(ch,0,sizeof ch);
}
void Insert(int node, int pos, int id, int num){
cnt[node]++;
if(pos<0){
val[node]=dp[id];
return;
}
int bit=(num>>pos)&1;
if(ch[node][bit]==0){
ch[node][bit]=++size;
val[size]=-1;
cnt[size]=0;
}
Insert(ch[node][bit], pos-1, id, num);
val[node]=max(val[node], val[ch[node][bit]]);
}
int Query(int node, int pos, int x, int num){
if(pos<0)
return val[node];
int xbit=(x>>pos)&1, nbit=(num>>pos)&1;
int ans=-1;
if(xbit){
if(ch[node][nbit])
ans = val[ch[node][nbit]];
if(ch[node][!nbit])
ans = max(ans, Query(ch[node][!nbit], pos-1, x, num));
}
else if(ch[node][nbit])
ans = Query(ch[node][nbit], pos-1, x, num);
return ans;
}
void Delete(int node, int pos, int num){
if(!--cnt[node])
val[node]=-1;
if(pos<0)
return;
int bit=(num>>pos)&1;
Delete(ch[node][bit], pos-1, num);
val[node]=val[ch[node][bit]];
if(ch[node][!bit])
val[node]=max(val[node],val[ch[node][!bit]]);
}
}trie;
int main(){
int t;
scanf("%d", &t);
while(t--){
int n,x,l;
scanf("%d%d%d", &n,&x,&l);
int p,q;
scanf("%d%d%d", &a[1],&p,&q);
for(int i=2;i<=n;++i)
a[i]=(a[i-1]*p+q)%M;
for(int i=2;i<=n;++i)a[i]^=a[i-1];
trie.init();trie.Insert(0,27,0,0);
for(int i=1;i<=n;++i){
if(i>l+1&&dp[i-l-1]!=-1)trie.Delete(0, 27, a[i-l-1]);
dp[i]=trie.Query(0, 27, x, a[i]);
if(dp[i]!=-1){
dp[i]++;
trie.Insert(0, 27, i, a[i]);
}
}
printf("%d\n", dp[n]==-1?0:dp[n]);
}
return 0;
}
【HDU - 5845】Best Division(xor-trie、01字典树、dp)的更多相关文章
- BZOJ 4260 Codechef REBXOR (区间异或和最值) (01字典树+DP)
<题目链接> 题目大意:给定一个序列,现在求出两段不相交的区间异或和的最大值. 解题分析: 区间异或问题首先想到01字典树.利用前缀.后缀建树,并且利用异或的性质,相同的两个数异或变成0, ...
- HDU5715 XOR 游戏 二分+字典树+dp
当时Astar复赛的时候只做出1题,赛后补题(很长时间后才补,懒真是要命),发现这是第二简单的 分析: 这个题,可以每次二分区间的最小异或和 进行check的时候用dp进行判断,dp[i][j]代表前 ...
- NBUT 1525 Cow Xor(01字典树+前缀思想)
[1525] Cow Xor 时间限制: 2000 ms 内存限制: 65535 K 问题描述 农民约翰在喂奶牛的时候被另一个问题卡住了.他的所有N(1 <= N <= 100,000)个 ...
- Xor Sum 01字典树 hdu4825
Xor Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total S ...
- Codeforces 979 字符串强制N变换最多出现字母 DFS子树 暴力01字典树
A /* Huyyt */ #include <bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define mkp(a,b) ...
- HDU 4825 Xor Sum(01字典树入门题)
http://acm.hdu.edu.cn/showproblem.php?pid=4825 题意: 给出一些数,然后给出多个询问,每个询问要从之前给出的数中选择异或起来后值最大的数. 思路:将给出的 ...
- hdu 4825 Xor Sum(01字典树模版题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825 题解:一到01字典树的模版题,01字典树就是就是将一些树用二进制放到一个树上这样可以方便对整体异 ...
- HDU 4825 Xor Sum (模板题)【01字典树】
<题目链接> 题目大意: 给定n个数,进行m次查找,每次查找输出n个数中与给定数异或结果最大的数. 解题分析: 01字典树模板题,01字典树在求解异或问题上十分高效.利用给定数据的二进制数 ...
- HDU 6625 (01字典树)
题意:给定两个长为n的数组a和b:重新排列a和b,生成数组c,c[i]=a[i] xor b[i]:输出字典序最小的c数组. 分析:将a中的数插入一颗01字典树a中:将b中的数插入一颗01字典树b中: ...
- Xor Sum---hdu4825(01字典树模板)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4825 题意:有n个数m个查找,每个查找有一个数x, 从序列中找到一个数y,使得x异或y最大 ...
随机推荐
- hdu5943素数间隙与二分匹配
题意: 给出n和s,匹配(s+1,s+2,s+3......s+n)和(1,2,3,4,5........n)让(s+x)%x==0,判断是否有解 思路: 先用程序跑一边,发现1到1e9得素数间隙小于 ...
- 机器学习第一篇——最近邻kNN
机器学习监督学习中,根据解决问题的连续性和离散型,分为分类问题和回归问题.最邻近算法kNN是一种最为直接和简便的分类方法. kNN本质上,是计算目标到模型的欧式距离,从而判定目标所属的类别. 首先,在 ...
- Linux 安装软件之后设置PATH环境变量
每一个软件都有安装路径这一项,指定安装路径的目的,一方面是便于文件搜索与查找,另一方面更方便的使用软件. 比如,几乎大多数自己安装的软件,都会选择安装在/usr/local目录下,比如apache.m ...
- MySQL中关于数据类型指定宽度之后的情况
概述 MySQL有很多种数据类型,最常用的就是int,char,varchar,这些类型在创建表的时候都可以指定该字段的宽度,方法是在类型后面加一个括号,括号中写宽度就可以了. 但是,在指定宽度之后, ...
- telnet总结
telnet是经常使用的客户端链接工具,总结一下常用的telnet的使用方法 1) 连接 telnet //链接swoole 2)退出当前连接 ctrl + ] 回车 3)查看常用的一些命令 ? 回车 ...
- React Native之TextInput的介绍与使用(富文本封装与使用实例,常用输入框封装与使用实例)
React Native之TextInput的介绍与使用(富文本封装与使用实例,常用输入框封装与使用实例) TextInput组件介绍 TextInput是一个允许用户在应用中通过键盘输入文本的基本组 ...
- IdentityServer4【QuickStart】之使用ClientCredentials流程保护API
使用ClientCredentials流程保护API 这个示例展示了使用IdentityServer中保护APIs的最基本的场景. 在这个场景中我们会定义一个API和一个想要访问它的客户端.客户端会在 ...
- java程序员一些初中级面试题(数据库部分)
说出一些数据库优化方面的经验? 1.从JDBC编程的角度讲,用PreparedStatement一般来说比Statement性能高,因为在使用时,SQL语句被预编译并存储在PreparedStatem ...
- [转帖]浅谈程序中的text段、data段和bss段
作者:百问科技链接:https://zhuanlan.zhihu.com/p/28659560来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 一般情况,一个程序本质上都 ...
- Java8 Lambda和Stream的用法
package com.zhangxueliang.demo; import java.util.ArrayList; import java.util.List; import java.util. ...