【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. 树(tree)

    树(tree)[题目描述]从前在森林里面有一棵很大的树,树上住着很多小动物.树上有

  2. ELK最佳实践

    1.ELK最佳实践解析 a.用户通过nginx或haproxy访问ELK日志统计平台,IP地址为keepalived的vip地址; b.nginx将请求转发到kibana; c.kibana到es获取 ...

  3. Ruby on rails初体验(二)

    体验一中添加了一个最基本的支架和一个简单的数据迁移,实现了一个基本的增删改查的功能列表.体验二中要在次功能上继续丰满一下功能.实现如下效果: 在每个公司中都包含有不同的部门,按照体验一中的方法,添加一 ...

  4. Java中的JAR/EAR/WAR包的文件夹结构说明(转)

    JAR包:打成JAR包的代码,一般作为工具类,在项目中,会应用到N多JAR工具包. WAR包:JAVA WEB工程,都是打成WAR包,进行发布,如果我们的服务器选择TOMCAT等轻量级服务器,一般就打 ...

  5. ios编程规范

    允许使用较长的描述尽量不要使用缩写,而是将完整的意思写出来.源于代码的维护可能会被不同文化背景的programmer阅读 适当的命名前缀,比如给变量,协议等,不要给方法加前缀 方法命名规则一般以小写字 ...

  6. Mac搭建python环境

    1 安装xcode 2 安装 brew ruby-e"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/mast ...

  7. Android WiFi开发教程(一)——WiFi热点的创建与关闭

    相对于BlueTooth,WiFi是当今使用最广的一种无线网络传输技术, 几乎所有智能手机.平板电脑和笔记本电脑都支持Wi-Fi上网.因此,掌握基本的WiFI开发技术是非常必要的.本教程将围绕一个小D ...

  8. Mycat本地模式的自增长分表操作

    Mycat对表t_rc_rule_monitor做分表操作 在mysql上执行(没有t_rc_rule_monitor) DROP TABLE IF EXISTS t_rc_rule_monitor; ...

  9. DNS_主从服务_详细搭建&&配置

    DNS主从 安装环境: 三台dns服务器如下: 系统:均为centos7 dns_master:192.168.169.194 dns_slave-1:192.168.169.195 dns_slav ...

  10. Tomcat的Manager显示403 Access Denied

    管理tomcat的时候遇到了以下问题: 1.刚开始需要用户名密码,不知道用户名和密码是什么,但是输入什么都不正确. 解决办法: 自己在tomcat-users.xml中按格式添加用户 conf文件夹里 ...