【题解】HDU5845 Best Division (tri树)
时间:2019-10-23
本文章向大家介绍【题解】HDU5845 Best Division (tri树),主要包括【题解】HDU5845 Best Division (tri树)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
【题解】HDU5845 Best Division (tri树)
题意:给定你一个序列(三个参数来根),然后请你划分子段。在每段子段长度小于等于\(L\)且子段的异或和\(\le x\)的情况下最大化分出子段的个数
区间/子段/序列这种东西一大性质就是右端点之后与前面无关。
\(dp(i)\)表示上一个右端点是\(i\)且前面分出来的子段都满足条件的最多子段个数。
直接转移\(O(n^2)\)考虑优化这个东西,子段转前缀和是应该记起来的套路,现在问题就是变成查询两个前缀和的异或值是否满足条件。
先不考虑\(L\)的限制
处理两者异或的数据结构=trie树,于是可以建立一颗01trie,trie的叶子节点可以表示一个值,建立trie输入的字符串就是他对应位置的前缀和。
考虑假如已经有了一个trie树了,在trie树上查询的实质是生成一个新的数。我们可以在生成这个数的时候根据该当前生成位上的新生成的那个数能否为\(1\),以及\(x\)是否为\(1\)讨论一下一个节点子树最大值。
查询子树最大值可以直接线段树+dfs序,但这是数据结构学傻的表现。可以发现trie树树高是\(\log n\)的,直接在插入的时候暴力跳父亲更新父亲的值即可。
考虑\(L\)的限制,这个限制就相当于要让这个trie树支持删除操作,可以每个节点套一个multiset,但这是stl用傻了的表现。可以发现dp数组的值是不降的(这里其实存疑),所以可以直接删。
复杂度\(O(n\log n)\)
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(!isdigit(c))f|=c==45,c=getchar();
while(isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const int mod=(1<<28)-1;
struct E{
int son[2],Max,cnt;
inline void clear(){memset(son,0,sizeof son);Max=0;cnt=0;}
inline int&operator[](int x){return son[x];}
inline void upd(const int&val,const int&tag){
if(tag==1){
if(Max<val) Max=val,cnt=1;
else if(Max==val) ++cnt;
}
else {
if(Max==val) --cnt;
if(cnt==0) Max=0;
}
}
}e[maxn*28];
int sum[maxn],dp[maxn],cnt,n,x,L,p,q;
inline void insert(const int&x,const int&val){
int now=0;
for(int t=27;~t;--t){
int g=x>>t&1;
if(!e[now][g]) e[now][g]=++cnt,e[cnt].clear();
now=e[now][g];
e[now].upd(val,1);
}
}
inline void Delete(const int&x,const int&val){
int now=0;
for(int t=27;~t;--t){
int g=x>>t&1;
now=e[now][g];
e[now].upd(val,-1);
}
}
inline int que(const int&s,const int&x){
int ret=-1,now=0;
for(int t=27;~t;--t){
int g=s>>t&1;
if(x>>t&1){
if(e[now][g]) ret=max(ret,e[e[now][g]].Max);
if(e[now][g^1]) now=e[now][g^1];
else return ret;
}
else{
if(e[now][g]) now=e[now][g];
else return ret;
}
}
ret=max(ret,e[now].Max);
return ret;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
#endif
int T=qr();
while(T--){
n=qr(); x=qr(); L=qr();
sum[1]=qr(); p=qr(); q=qr();
memset(e,0,sizeof e);
e[cnt=0].clear();
for(int t=2;t<=n;++t) sum[t]=(1ll*sum[t-1]*p+q)&mod;
for(int t=2;t<=n;++t) sum[t]^=sum[t-1];
memset(dp,-1,sizeof dp);
insert(0,0); dp[0]=0;
for(int t=1,l=t-L-1,k;t<=n;++t,++l){
if(l>=0) if(dp[l]>=0) Delete(sum[l],dp[l]);
k=que(sum[t],x);
if(k>=0) dp[t]=k+1,insert(sum[t],dp[t]);
}
printf("%d\n",dp[n]==-1?0:dp[n]);
}
return 0;
}
原文地址:https://www.cnblogs.com/winlere/p/11725419.html
- 无需开启宏即可渗透:在Office文档中利用DDE执行命令
- SQLiv:一款批量SQL注入漏洞扫描工具
- 【Python环境】监督学习之KNN算法
- 【数据科学】什么是数据科学家与数据科学
- Android基础总结(12)——XML和JSON解析
- 【Python环境】scikit-learn的线性回归模型
- Android基础总结(8)——服务
- 你需要每天写代码吗?
- Java基础——多线程
- No.010 Regular Expression Matching
- JavaScript依赖注入的实现思路
- No.011 Container With Most Water
- No.009 Palindrome Number
- Windows DNS API RCE漏洞分析及PoC构造
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 在页面上写一个验证码
- 缓冲字节输出流BufferedOutputStream
- EL表达式获取简单数据与复杂数据(调用类)+EL表达式获取Map集合与list集合数据
- 用缓冲字节流,复制一个照片
- 09小结:封装结果集或实体类时,有多个对象的解决方法
- 序列化与反序列化Serializable,Externalizable
- response.getWriter().write()和 response.getWriter().print()的区别:
- java使用TCP,由客户端向服务端传输图片,(电脑与电脑)或(同一台电脑)
- 使用druid
- UDP实现多人聊天室
- 请求(doFilter)与响应乱码(BaseController+自定义注解@ContentType(““))集中处理
- 反射:Reflect(获取类对象三种方法)
- getParameterMap()返回参数需要对应实体类类型,否则收不到----打卡
- 类对象 与 类的对象
- Lambda什么时候使用+简化匿名内部类