【BZOJ3217】ALOEXT

Description

taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手。

突然有一天,taorunz来到了一个密室,里面放着一排可移动存储器,存储器里有非常珍贵的OI资料……不过比较特殊的是,每个存储器上都写着一个非负整数。taorunz很高兴,要把所有的存储器都拿走(taorunz的智商高达500,他一旦弄走了这里的所有存储器,在不久到来的AHOI和NOI中……你懂的)。不过这时有一个声音传来:“你只能拿走这里的一个存储器,而且还不能直接拿,你需要指定一段区间[l, r],满足l<r,然后在第l个和第r个存储器之间选一个拿走,你能获得的知识增加量等于区间[l, r]中所有存储器上写的整数的次大值与你拿走的这个存储器上写的整数作按位异或运算的结果。”

问题是,这里的可移动存储器数量太多,而且,它们还在不断地发生变化,有时候天上会掉下来一个新的存储器,并插入到这一排存储器中,有时候某个存储器会不明原因消失,有时候某个存储器上写的整数变化了。taorunz虽然智商很高,但也无法应对如此快的变化,他指定了许多段区间,让你帮他找出如果在这个区间中拿走存储器,他能获得的最多的知识是多少。

Input

第一行两个整数N、M,表示一开始的存储器数和后面发生的事件数。

第二行N个非负整数,表示一开始从左到右每个存储器上写的数字。注意,存储器从0开始编号,也就是最左边的存储器是第0个。

接下来M行,每行描述一个事件,有4种可能的事件。

(1)I x y:表示天上掉下来一个写着数字y的存储器,并插入到原来的第x个存储器之前,如果x等于原来存储器的个数,则插入到末尾;

(2)D x:表示第x个存储器消失;

(3)C x y:表示第x个存储器上写的数字变为y;

(4)F l r:表示taorunz指定区间[l, r],让你告诉他最多能获得多少知识。

注意,本题强制在线,也就是事件中出现的所有数字都进行了加密,数字s表示的真实值是

对于I、D、C事件中的x及F事件中的l、r:(s+last_ans) mod n0;

对于I、C事件中的y:(s+last_ans) mod 1048576。

其中n0为目前存储器个数,last_ans为上一个F事件的结果,如果前面尚未发生F事件,则last_ans=0。

Output

对于每个F事件,输出结果。

Sample Input

5 10
2 6 3 8 7
F 1 4
I 2 1048565
I 0 1048566
D 3
F 3 0
I 3 1048569
D 5
C 1 1048570
F 1 2
F 2 1

Sample Output

15
7
4
7

HINT

1<=N, M<=100000。所有F事件满足l<r。
本题共有5组数据,除1组为随机数据外,其它数据均为人工构造。

题解:直接替罪羊树套Trie树。外层直接在替罪羊树上维护最大值和次大值,然后查询时将区间中对应的log个Trie树提取出来,一起跑一个贪心即可。

替罪羊树的删除有两种写法,一种是将前驱或后继提上来,一种是打标记。我采取的是打标记的方式,虽然特判比较多~看代码吧。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn=200010;
const int mod=1048576;
int n0,n,m,ans,tot,root,last,flast;
struct trie
{
int ch[2],siz;
}s[30000010];
struct node
{
int s1,s2;
node(){}
node(int a,int b){s1=a,s2=b;}
}sec;
struct tzy
{
int ls,rs,siz,msiz,rt,val,fa;
node sm;
}t[maxn];
int p[maxn],pp[maxn];
char str[5];
queue<int> q;
void pushup(node &x,node y)
{
if(y.s1>x.s1) x.s2=max(x.s1,y.s2),x.s1=y.s1;
else x.s2=max(x.s2,y.s1);
}
void insert(int &x,int y,int val)
{
if(!x) x=q.front(),q.pop();
int u=x,i,d;
for(i=1<<20;i;i>>=1)
{
d=((y&i)>0);
if(!s[u].ch[d]) s[u].ch[d]=q.front(),q.pop();
u=s[u].ch[d],s[u].siz+=val;
}
}
int query(int val)
{
int i,j,d,ret=0;
for(i=1<<20;i;i>>=1)
{
d=!(val&i);
for(j=1;j<=p[0];j++)
{
if(s[s[p[j]].ch[d]].siz)
{
ret|=i;
break;
}
}
if(j>p[0]) d^=1;
for(j=1;j<=p[0];j++) p[j]=s[p[j]].ch[d];
}
for(i=1;i<=pp[0];i++) ret=max(ret,val^pp[i]);
return ret;
}
int build(int l,int r,int from)
{
if(l>r) return 0;
int mid=(l+r)>>1,x=p[mid],i;
t[x].ls=build(l,mid-1,x),t[x].rs=build(mid+1,r,x),t[x].siz=t[x].msiz=r-l+1,t[x].rt=0,t[x].fa=from;
t[x].sm.s1=t[x].val,t[x].sm.s2=-1;
if(t[x].ls) t[t[x].ls].fa=x,pushup(t[x].sm,t[t[x].ls].sm);
if(t[x].rs) t[t[x].rs].fa=x,pushup(t[x].sm,t[t[x].rs].sm);
for(i=l;i<=r;i++) insert(t[x].rt,t[p[i]].val,1);
return x;
}
void del(int &x)
{
if(!x) return ;
del(s[x].ch[0]),del(s[x].ch[1]),s[x].siz=0,q.push(x),x=0;
}
void dfs(int x)
{
if(!x) return ;
dfs(t[x].ls);
if(t[x].val>=0) p[++p[0]]=x;
dfs(t[x].rs),del(t[x].rt);
}
void add(int &x,int y,int from)
{
if(!x)
{
x=n,t[x].sm.s1=t[x].val,t[x].sm.s2=-1,t[x].ls=t[x].rs=t[x].rt=0,t[x].fa=from,t[x].siz=t[x].msiz=1;
insert(t[x].rt,t[x].val,1);
return ;
}
if(y>=t[t[x].ls].siz+(t[x].val>=0)) add(t[x].rs,y-t[t[x].ls].siz-(t[x].val>=0),x);
else add(t[x].ls,y,x);
insert(t[x].rt,t[n].val,1),t[x].siz++,pushup(t[x].sm,t[n].sm);
t[x].msiz=t[t[x].ls].msiz+t[t[x].rs].msiz+1;
if(t[t[x].ls].msiz>t[x].msiz*0.75||t[t[x].rs].msiz>t[x].msiz*0.75) last=x,flast=from,t[x].msiz=t[x].siz;
}
void find(int x,int a,int b)
{
if(!x||a>b) return ;
if(a==1&&b==t[x].siz)
{
pushup(sec,t[x].sm);
p[++p[0]]=t[x].rt;
return ;
}
if(a>t[t[x].ls].siz+(t[x].val>=0)) find(t[x].rs,a-t[t[x].ls].siz-(t[x].val>=0),b-t[t[x].ls].siz-(t[x].val>=0));
else if(b<=t[t[x].ls].siz) find(t[x].ls,a,b);
else
{
find(t[x].ls,a,t[t[x].ls].siz);
if(t[x].val>=0) pp[++pp[0]]=t[x].val,pushup(sec,node(t[x].val,-1));
find(t[x].rs,1,b-t[t[x].ls].siz-(t[x].val>=0));
}
}
int getval(int x,int y)
{
if(y>t[t[x].ls].siz+(t[x].val>=0)) return getval(t[x].rs,y-t[t[x].ls].siz-(t[x].val>=0));
if(y<=t[t[x].ls].siz) return getval(t[x].ls,y);
return t[x].val;
}
void dec(int x,int y,int z)
{
if(y>t[t[x].ls].siz+(t[x].val>=0)) dec(t[x].rs,y-t[t[x].ls].siz-(t[x].val>=0),z);
else if(y<=t[t[x].ls].siz) dec(t[x].ls,y,z);
else t[x].val=-1;
t[x].sm.s1=t[x].val,t[x].sm.s2=-1,t[x].siz--;
insert(t[x].rt,z,-1);
if(t[x].ls) pushup(t[x].sm,t[t[x].ls].sm);
if(t[x].rs) pushup(t[x].sm,t[t[x].rs].sm);
}
void modify(int x,int y,int a,int b)
{
if(y>t[t[x].ls].siz+(t[x].val>=0)) modify(t[x].rs,y-t[t[x].ls].siz-(t[x].val>=0),a,b);
else if(y<=t[t[x].ls].siz) modify(t[x].ls,y,a,b);
else t[x].val=b;
insert(t[x].rt,a,-1),insert(t[x].rt,b,1);
t[x].sm.s1=t[x].val,t[x].sm.s2=-1;
if(t[x].ls) pushup(t[x].sm,t[t[x].ls].sm);
if(t[x].rs) pushup(t[x].sm,t[t[x].rs].sm);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n0=n=rd(),m=rd();
int i,a,b,c,u;
for(i=1;i<=30000000;i++) q.push(i);
for(i=1;i<=n;i++) t[i].val=rd(),p[i]=i;
root=build(1,n,0);
for(i=1;i<=m;i++)
{
scanf("%s",str);
if(str[0]=='I')
{
a=(rd()+ans)%n0,b=(rd()+ans)%mod,n0++;
t[++n].val=b,last=0,add(root,a,0);
if(last)
{
p[0]=0,dfs(last);
if(!flast) root=build(1,p[0],0);
else if(last==t[flast].ls) t[flast].ls=build(1,p[0],flast);
else t[flast].rs=build(1,p[0],flast);
for(u=last;u;u=t[u].fa) t[u].msiz=t[t[u].ls].msiz+t[t[u].rs].msiz+1;
}
}
if(str[0]=='D')
{
a=(rd()+ans)%n0+1,b=getval(root,a),n0--;
dec(root,a,b);
}
if(str[0]=='C')
{
a=(rd()+ans)%n0+1,b=(rd()+ans)%mod,c=getval(root,a);
modify(root,a,c,b);
}
if(str[0]=='F')
{
a=(rd()+ans)%n0+1,b=(rd()+ans)%n0+1;
p[0]=pp[0]=0,sec.s1=sec.s2=-1,find(root,a,b);
ans=query(sec.s2);
printf("%d\n",ans);
}
}
return 0;
}//5 10 2 6 3 8 7 F 1 4 I 2 1048565 I 0 1048566 D 3 F 3 0 I 3 1048569 D 5 C 1 1048570 F 1 2 F 2 1

【BZOJ3217】ALOEXT 替罪羊树+Trie树的更多相关文章

  1. Atitit 常见的树形结构 红黑树  二叉树   B树 B+树  Trie树 attilax理解与总结

    Atitit 常见的树形结构 红黑树  二叉树   B树 B+树  Trie树 attilax理解与总结 1.1. 树形结构-- 一对多的关系1 1.2. 树的相关术语: 1 1.3. 常见的树形结构 ...

  2. 字典树(Trie树)的实现及应用

    >>字典树的概念 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树.与二叉查找树不同,Trie树的 ...

  3. [POJ] #1002# 487-3279 : 桶排序/字典树(Trie树)/快速排序

    一. 题目 487-3279 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 274040   Accepted: 48891 ...

  4. 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树

    正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...

  5. luoguP6623 [省选联考 2020 A 卷] 树(trie树)

    luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...

  6. [转载]字典树(trie树)、后缀树

    (1)字典树(Trie树) Trie是个简单但实用的数据结构,通常用于实现字典查询.我们做即时响应用户输入的AJAX搜索框时,就是Trie开始.本质上,Trie是一颗存储多个字符串的树.相邻节点间的边 ...

  7. 字典树 Trie树

    什么是Trie树? 形如 其中从根节点到红色节点的路径上的字母所连成的字符串即为一个Trie树上所存的字符串. 比如,这个trie树上有ab,abc,bd,dda这些字符串. 至于怎么构建和查找或添加 ...

  8. 【HDU - 5790 】Prefix(主席树+Trie树)

    BUPT2017 wintertraining(15) #7C 题意 求[min((Z+L)%N,(Z+R)%N)+1,max((Z+L)%N,(Z+R)%N)+1]中不同前缀的个数,Z是上次询问的结 ...

  9. Luogu P2922 [USACO08DEC]秘密消息Secret Message 字典树 Trie树

    本来想找\(01Trie\)的结果找到了一堆字典树水题...算了算了当水个提交量好了. 直接插入模式串,维护一个\(Trie\)树的子树\(sum\)大小,求解每一个文本串匹配时走过的链上匹配数和终点 ...

随机推荐

  1. android实现多条件筛选列表菜单筛选菜单

    封装组合控件实现一个简单的多条件筛选菜单,可根据自己需求定制筛选条件,动态添加筛选项,灵活使用. 控件封装,点击切换,使用popupWindow实现下拉列表,项目中封装了多种数组数据排序处理方法的工具 ...

  2. HRBUST 1211 火车上的人数【数论解方程/模拟之枚举+递推】

    火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人.从第3站起(包括第3站 ...

  3. Codeforces 482B Interesting Array(线段树区间更新)

    题目链接 Interesting Array 区间更新.然后对于每一个约数重新求一遍区间的&值,不符合就跳出. #include <bits/stdc++.h> using nam ...

  4. mac搭建安卓开发环境

    下载 android studio,利用android studio自带sdk manager下载安卓sdk,在sdk manager中设置相关代理地址,下载完sdk后,在bash_profile中把 ...

  5. iOS for循环创建button,button的宽度依据上面的文字来自适应.

    近期须要使用一个标签页,寻思自己写一个demo. 标签的大小依据上面的文字来自适应大小,须要依据后台返回的数据自己主动换行.没有加入 NSArray *arr = @[@"无知", ...

  6. from: Maven实战(九)——打包的技巧

    from : http://www.infoq.com/cn/news/2011/06/xxb-maven-9-package 要点: 1. 打出可执行的jar包, 2. 自定义打包

  7. linux中grep注意

    grep -l 只输出文件名: -h 只输出匹配的行 不输出文件名: -c 之处匹配内容的行数: -n 将结果输出的同时,也输出改行的行号: -c 统计查到的总行数: -i 忽略大小写: grep ' ...

  8. 未经处理的异常在 System.Data.dll 中发生。其它信息:在应使用条件的上下文(在 &#39;***&#39; 附近)中指定了非布尔类型的表达式。

    机房收费系统中,有些人在联合查询这个模块用的是存储过程.我先尝试着在数据库中建立了一个视图.然后在UI层做个推断并生成查询条件strCondition. 在机房收费系统的"联合查询" ...

  9. C# Winform 运行异常 CefSharp.core.dll 找不到指定的模块

    C# Winform开发中使用了CefSharp,之前在VS2012中运行很正常,今天换了一台Windows XP 打开VS2010 运行时,发生异常:System.IO.FileNotFoundEx ...

  10. RF ---library

    RF内置库: http://robotframework.org/robotframework/ SSHLibrary:   ---WEB自动化测试 http://robotframework.org ...