---恢复内容开始---

  HAOI 2019 DAY1 T1 我爆零了。

爆零的感觉很难受 原因竟然是我从没犯过的错误 审题不清。情绪低迷。

也许 也许 也许就是想让我知道我有多菜吧。

求前k大的区间异或值 。我硬生生读错题目 想着将区间分成k段 求划分整个区间的最大值。

我还写了一个n^3的dp 觉得只能过60 然后搞了一棵trie树 觉得能过80 然后 发现GG了

这个读错题的我就非常的毒瘤了。 我的RP可能是谷底了吧。

这个范围 60分随便写啊 n^2暴力 然后 放堆里出来k个即可。

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<algorithm>
#include<vector>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#include<cmath>
#define ll long long
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline ll read()
{
ll x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(ll x)
{
x<?putchar('-'),x=-x:;
ll num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const ll MAXN=;
ll n,k,ans;
ll a[MAXN],w[MAXN];
priority_queue<ll> q;
int main()
{
//freopen("1.in","r",stdin);
n=read();k=read();
for(ll i=;i<=n;++i)
{
a[i]=read();
w[i]=(a[i]^w[i-]);
q.push(w[i]);
}
for(ll i=;i<=n;++i)
for(ll j=i+;j<=n;++j)
{
ll x=(w[i]^w[j]);
q.push(x);
}
for(ll i=;i<=k;++i)
{
ans+=q.top();
q.pop();
}
put(ans);
return ;
}

考虑正解 首先构建01trie 自然 考虑如何求出第k大 好像不太好求 因为我好像没办法标记 或者说标记某个东西用过了的话会很困难的。

所以这时 可持久化trie 就出来了 也很自然吧 像主席树一般。

求第k大这不秒了么,主席树就是来求第k大的 然后 每次根据某个右端点求出左端点即可。

很简单的题目我却因为 种种非常蠢的原因爆零 甚至连 60都搞不到真是服气我自己 机会不多,自己不珍惜那么 将会永远后悔。

值得一提的是 这道题在loj上我自己写的大常数代码秒过但是洛谷上就 一直T

各种优化常数 这里我总结一下T一个点或几个点的优化方法:

1 不要将所有的 int 都换成long long 这样会很慢的。

2 加上inline Register

3 空间开的不要过大

4 一些不需要的代码可以优化的要进行优化。

// luogu-judger-enable-o2
//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<algorithm>
#include<vector>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#include<cmath>
#define ll long long
#define R register
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline ll read()
{
ll x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(ll x)
{
x<?putchar('-'),x=-x:;
ll num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const ll MAXN=,maxn=;
ll n,k,ans,cnt,sum;
ll w[MAXN];
int root[MAXN],rank[MAXN];
int trie[MAXN*maxn][],sz[MAXN*maxn];
priority_queue<pair<ll,int> > b;
inline void insert(int &now,int last,int depth,ll x)
{
if(!now)now=++cnt;
if(depth==)
{
sz[now]++;
sz[now]+=sz[last];
return;
}
int tn=(x>>(depth-))&;
trie[now][tn^]=trie[last][tn^];
insert(trie[now][tn],trie[last][tn],depth-,x);
sz[now]=sz[trie[now][tn]]+sz[trie[now][tn^]];
return;
}
inline void find(int now,int k,int depth,ll x)
{
//if((!trie[now][0])&&(!trie[now][1]))return;
if(depth==)return;
ll tn=(x>>(depth-))&;
if(sz[trie[now][tn^]]>=k)
{
ans=(ans<<)|;
find(trie[now][tn^],k,depth-,x);
}
else
{
ans=ans<<;
find(trie[now][tn],k-sz[trie[now][tn^]],depth-,x);
}
return;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();k=read();
for(R int i=;i<=n;++i)
{
ll x=read();
rank[i]=;
w[i]=(x^w[i-]);
}
insert(root[],root[],,);
for(R int i=;i<=n;++i)insert(root[i],root[i-],,w[i]);
for(R int i=;i<=n;++i)
{
ans=;
find(root[i],rank[i],,w[i]);
++rank[i];
b.push(make_pair(ans,i));
//put(ans);
}
for(R int i=;i<=k;++i)
{
int l=b.top().second;
ll z=b.top().first;
b.pop();sum+=z;//put(z);
ans=;
find(root[l],rank[l],,w[l]);
++rank[l];
b.push(make_pair(ans,l));
}
put(sum);
return ;
}

要是我能刷到这道题 也不至于会爆零了吧 我会证明我有坚强的毅力刷这个题库的。

再次看错了题目 两个数之间的异或最大值并非一段区间的最大值。

这样的话就会比上面的题目就比较简单了。

/**************************************************************
Problem: 3689
User: chdy
Language: C++
Result: Accepted
Time:5056 ms
Memory:43884 kb
****************************************************************/ //#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<algorithm>
#include<vector>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#include<cmath>
#define ll long long
#define INF -1
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(int x)
{
x<?putchar('-'),x=-x:;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar(' ');return;
}
const int MAXN=,maxn=;
int n,k,cnt,ans;
int sz[MAXN*maxn],root[MAXN],rank[MAXN];
int a[MAXN],trie[MAXN*maxn][];
struct wy
{
int x,z;
friend int operator <(wy a,wy b){return a.z>b.z;}
};
priority_queue<wy>q;
inline void insert(int &now,int last,int depth,int x)
{
if(!now)now=++cnt;
if(depth==)
{
sz[now]++;
sz[now]+=sz[last];
return;
}
int tn=(x>>(depth-))&;
trie[now][tn^]=trie[last][tn^];
insert(trie[now][tn],trie[last][tn],depth-,x);
sz[now]=sz[trie[now][tn]]+sz[trie[now][tn^]];
return;
}
inline void find(int now,int depth,int k,int x)
{
if(depth==)return;
if(sz[trie[now][]]+sz[trie[now][]]<k){ans=INF;return;}
int tn=(x>>(depth-))&;
if(sz[trie[now][tn]]>=k)
{
ans=ans<<;
find(trie[now][tn],depth-,k,x);
}
else
{
ans=ans<<|;
find(trie[now][tn^],depth-,k-sz[trie[now][tn]],x);
}
return;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();k=read();
for(int i=;i<=n;++i)a[i]=read(),rank[i]=;
for(int i=;i<=n;++i)insert(root[i],root[i-],,a[i-]);
for(int i=;i<=n;++i)
{
ans=;
find(root[i],,rank[i],a[i]);
++rank[i];
q.push((wy){i,ans});
}
for(int i=;i<=k;++i)
{
int l=q.top().x;
int xx=q.top().z;
q.pop();ans=;
if(i!=k)put(xx);
else printf("%d\n",xx);
find(root[l],,rank[l],a[l]);
++rank[l];
if(ans!=-)q.push((wy){l,ans});
}
return ;
}

这道题就是典型的 可持久化trie 树的应用了 当然 比较基础。

因为这些都不带修改 带修改的trie树 可能 就可以树套树了 像带修改的主席树一般。

针对这道题 求 A[p]~A[N]^x之间的最大异或和 考虑 取前缀和那么问题转换成了 w[N]^x^w[p-1];

至于 p的范围 l~r之间 所以p-1 就是l-1~r-1之间了 取决策时 只需在r-1这个trie树上取。

至于l-1 让r-1 - l-2的值 然后判断是否可走即可。

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<algorithm>
#include<vector>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#include<cmath>
#define ll long long
#define R register
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void put(int x)
{
x<?putchar('-'),x=-x:;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=,maxn=;
int n,m,cnt,ans;
int trie[MAXN*maxn][],sz[MAXN*maxn];
int w[MAXN],root[MAXN];
char ch[];
inline void insert(int &now,R int last,R int depth,R int x)
{
if(!now)now=++cnt;
if(!depth)
{
++sz[now];
sz[now]+=sz[last];
return;
}
R int tn=x>>(depth-)&;
trie[now][tn^]=trie[last][tn^];
insert(trie[now][tn],trie[last][tn],depth-,x);
sz[now]=sz[trie[now][tn]]+sz[trie[now][tn^]];
}
inline void find(R int now,R int last,R int depth,R int x)
{
if(!depth)return;
R int tn=x>>(depth-)&;
if(last==-)
{
if(sz[trie[now][tn^]]>)
{
ans=ans<<|;
find(trie[now][tn^],last,depth-,x);
}
else
{
ans=ans<<;
find(trie[now][tn],last,depth-,x);
}
return;
}
if(sz[trie[now][tn^]]-sz[trie[last][tn^]]>)
{
ans=ans<<|;
find(trie[now][tn^],trie[last][tn^],depth-,x);
}
else
{
ans=ans<<;
find(trie[now][tn],trie[last][tn],depth-,x);
}
return;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
for(R int i=;i<=n;++i)w[i]=read()^w[i-];
insert(root[],root[],,);
for(R int i=;i<=n;++i)insert(root[i],root[i-],,w[i]);
for(R int i=;i<=m;++i)
{
R int x,l,r;
scanf("%s",ch+);
if(ch[]=='A')
{
x=read();++n;
w[n]=x^w[n-];
insert(root[n],root[n-],,w[n]);
}
else
{
l=read();r=read();x=read();
ans=;
find(root[r-],(l->=)?root[l-]:-,,x^w[n]);
put(ans);
}
}
return ;
}

注意边界 减到-1的处理。。。

当然 书上还有较为简洁的代码,但是我自认为自己代码的常数小所以就不抄书上的代码了。

还是自己写的好!(其实大致思路都是一样的)

可持久化trie 就到这里了 其实真的跟主席树差不多。

可持久化Trie的更多相关文章

  1. HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)

    Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Su ...

  2. 【BZOJ4260】 Codechef REBXOR 可持久化Trie

    看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...

  3. 可持久化Trie & 可持久化平衡树 专题练习

    [xsy1629]可持久化序列 - 可持久化平衡树 http://www.cnblogs.com/Sdchr/p/6258827.html [bzoj4260]REBXOR - Trie 事实上只是一 ...

  4. HDU 4757 Tree(可持久化trie)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4757 题意:给出一棵树,节点有权值.每次询问x到y的路径上与z抑或的最大值. 思路:可持久化trie. ...

  5. 可持久化trie 学习总结

    QAQ 以前一直觉得可持久化trie很难,今天强行写了一发觉得还是蛮简单的嘛 自己的模板是自己手写的,写了几道题目并没有出过错误 THUSC的第二题的解法五貌似就是可持久化trie,时间复杂度O(60 ...

  6. [BZOJ 4103] [Thu Summer Camp 2015] 异或运算 【可持久化Trie】

    题目链接:BZOJ - 4103 题目分析 THUSC滚粗之后一直没有写这道题,从来没写过可持久化Trie,发现其实和可持久化线段树都是一样的.嗯,有些东西就是明白得太晚. 首先Orz ZYF-ZYF ...

  7. bzoj 2741: 【FOTILE模拟赛】L 分塊+可持久化trie

    2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1116  Solved: 292[Submit][Status] ...

  8. bzoj 2741 分块+可持久化trie

    多个询问l,r,求所有子区间异或和中最大是多少 强制在线 做法: 分块+可持久化trie 1.对于每块的左端点i,预处理出i到任意一个j,()i,j)间所有子区间异或和中最大为多少,复杂度O(\(n\ ...

  9. 【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L

    Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 .. ...

  10. HDU4757--Tree 可持久化trie + LCA

    题意:n个点的树,Q次询问,询问u-v路径上的点的权值与z抑或的最大值. 先考虑,在一个区间上的问题,可以先建一个可持久化的Trie,然后每次询问,就和线段树的操作差不多,从最高位开始考虑选1还是选0 ...

随机推荐

  1. Swift 拷贝文件夹,实现文件夹内容整体复制

    我们知道,在沙盒内,iOS要拷贝一个文件,可以使用 fileManager.copyItem(atPath: fullPath, toPath: fulltoPath) 方法简单实现,不过当我们要拷贝 ...

  2. 飞思卡尔单片机P&E开发工具硬件及软件

    原文链接: http://blog.sina.com.cn/s/blog_8ebff8d7010121tm.html 1.HC(S)08系列 开发机硬件:USB-ML-12 CYCLONE PRO U ...

  3. css世界的学习笔记

    1.+选择器div+p:选择紧接在div后的所有p元素: 2.导航的样式:(注意:不给a设置width:100%;只是需要display:block;利用流布居:) <h4>无宽度,借助流 ...

  4. ASP.NET MVC 右键点击添加没有区域(Area)、控制器、试图等选项

    在MVC项目中准备添加控制器.区域时发现没有控制器这个选项,当时没有在意以为VS出问题了,网上所搜了一下,有人说没有安装:Microsoft.AspNet.Mvc或者需要升级. 本次的解决如下: 1) ...

  5. Replication基础(六) 复制中的三个线程(IO/SQL/Dump)

    Reference:  https://blog.csdn.net/sun_ashe/article/details/82181811?utm_source=blogxgwz1 简介在MySQL复制技 ...

  6. Android WebRTC开发入门

    在学习 WebRTC 的过程中,学习的一个基本步骤是先通过 JS 学习 WebRTC的整体流程,在熟悉了整体流程之后,再学习其它端如何使用 WebRTC 进行互联互通. 申请权限 Camera 权限 ...

  7. SSH使用小记

    0.是什么 SSH(Secure Shell)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境.(更多详情可参阅维基百科 https://zh.wikipedia.org/wi ...

  8. 乾坤合一~Linux设备驱动之块设备驱动

    1. 题外话 在蜕变成蝶的一系列学习当中,我们已经掌握了大部分Linux驱动的知识,在乾坤合一的分享当中,以综合实例为主要讲解,在一个月的蜕茧成蝶的学习探索当中,觉得数据结构,指针,链表等等占据了代码 ...

  9. redis服务器学习一

    一:什么是redis服务器 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zs ...

  10. 8051汇编:EQU指令

    关于EQU汇编指令 EQU是英文单词equal的缩写,因此我们也能对EQU指令有一个初步的认识:做等价替换使用. 在8051汇编语言中,EQU用于定义一个符号常量,其效果不会带来存储空间的占用(这和C ...