Description

火星上的一条商业街里按照商店的编号 \(1\),\(2\) ,…,\(n\) ,依次排列着 \(n\) 个商店。商店里出售的琳琅满目的商品中,每种商品都用一个非负整数 \(val\) 来标价。每个商店每天都有可能进一些新商品,其标价可能与已有商品相同。

火星人在这条商业街购物时,通常会逛这条商业街某一段路上的所有商店,譬如说商店编号在区间 \([L,R]\) 中的商店,从中挑选1件自己最喜欢的商品。每个火星人对商品的喜好标准各不相同。通常每个火星人都有一个自己的喜好密码 \(x\) 。对每种标价为 \(val\) 的商品,喜好密码为 \(x\) 的火星人对这种商品的喜好程度与 \(val\) 异或 \(x\) 的值成正比。也就是说,\(val\) \(xor\) \(x\) 的值越大,他就越喜欢该商品。每个火星人的购物卡在所有商店中只能购买最近 \(d\) 天内(含当天)进货的商品。另外,每个商店都有一种特殊商品不受进货日期限制,每位火星人在任何时刻都可以选择该特殊商品。每个商店中每种商品都能保证供应,不存在商品缺货的问题。

对于给定的按时间顺序排列的事件,计算每个购物的火星人的在本次购物活动中最喜欢的商品,即输出 \(val\) \(xor\) \(x\) 的最大值。这里所说的按时间顺序排列的事件是指以下 \(2\) 种事件:

事件 \(0\), 用三个整数 \(0\) , \(s\) , \(v\) ,表示编号为 \(s\) 的商店在当日新进一种标价为 \(v\) 的商品。

事件 \(1\),用 \(5\) 个整数 \(1\) , $ L$ , \(R\) , \(x\) , \(d\) ,表示一位火星人当日在编号为 \(L\) 到 \(R\) 的商店购买 \(d\) 天内的商品,该火星人的喜好密码为 \(x\) 。

Input

第1行中给出2个正整数 \(n\) , \(m\) ,分别表示商店总数和事件总数。

第2行中有 \(n\) 个整数,第 \(i\) 个整数表示商店 \(i\) 的特殊商品标价。

接下来的 \(m\) 行,每行表示 \(1\) 个事件。每天的事件按照先事件 \(0\), 后事件 \(1\) 的顺序排列。

Output

将计算出的每个事件 \(1\) 的 \(val\) \(xor\) \(x\) 的最大值依次输出。

Sample Input

4 6

1 2 3 4

1 1 4 1 0

0 1 4

0 1 3

1 1 1 1 0

1 1 1 1 1

1 1 2 1 2

Sample Output

5

0

2

5

HINT

\(n, m \leq 100000\)

数据中,价格不大于 \(100000\)


想法

首先吐槽题面!没见过比它说得更不清楚更恶心的了。。。

“每天”的定义:出现事件0 就是新一天的开始,在第一个事件0出现前的事件可看作第0天的。

要求异或和最大有两种方法,一种是线性基,一种是可持久化 \(trie\) ,这道题中可持久化 \(trie\) 更方便。

对于不受时间限制的特殊商品,直接以商店编号为版本号建一个 可持久化 \(trie\) ,查询、更新答案。

其他操作咋一看好像很复杂。

但如果商店编号当作 \(x\) 轴,时间当作 \(y\) 轴,其实就是 添加单点+二维矩阵查询与 \(x\) 的最大异或和。

那就需要树套树(线段树+可持久化 \(trie\))了。

以商店编号为下标建线段树,在线段树每个节点以时间为版本号建 可持久化 \(trie\) (反过来也行啦~)

但如果这样空间受不住。

于是线段树分治。

将每个每个查询拆成 \(O(logn)\) 份放到线段树节点上

遍历线段树的每个节点,现场建树、查询、更新答案。

总复杂度 \(O(nlog^2n)\)


代码

这代码……不太好写也不太好调。

唯一的安慰是数据弱,调过样例后就 \(1A\) 了。

(\(ps\) 指针选手似乎变为数组选手了呢……)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring> using namespace std; int read(){
int x=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x;
} const int N = 100005; struct commo{ int x,d; };
struct query{ int x,l,r,id; };
int n,m;
int spi[N],ans[N]; int rt[N],cnt2,son[N*20][2],sum[N*20];
void clear(int x){
for(int i=0;i<cnt2;i++) son[i][0]=son[i][1]=0,sum[i]=0;
cnt2=0;
for(int i=0;i<=x;i++) rt[i]=0;
if(x==-1) memset(rt,0,sizeof(rt));
}
void insert(int x,int pre,int dep,int c){
if(dep==-1) { sum[x]=sum[pre]+1; return; }
int f=((c>>dep)&1);
son[x][f^1]=son[pre][f^1];
insert(son[x][f]=++cnt2,son[pre][f],dep-1,c);
sum[x]=sum[pre]+1;
}
int ask(int x,int pre,int dep,int c){
if(dep==-1) return 0;
int f=((c>>dep)&1);
if(sum[son[x][f^1]]>sum[son[pre][f^1]]) return (1<<dep)+ask(son[x][f^1],son[pre][f^1],dep-1,c);
return ask(son[x][f],son[pre][f],dep-1,c);
} int root,cnt;
int ch[N*2][2];
vector<commo> v[N*2];
vector<query> q[N*2];
void build(int x,int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
build(ch[x][0]=++cnt,l,mid);
build(ch[x][1]=++cnt,mid+1,r);
}
void modify(int x,int l,int r,int c,commo d){
v[x].push_back(d);
if(l==r) return;
int mid=(l+r)>>1;
if(c<=mid) modify(ch[x][0],l,mid,c,d);
else modify(ch[x][1],mid+1,r,c,d);
}
void add(int x,int l,int r,int L,int R,query d){
if(l>=L && r<=R) { q[x].push_back(d); return; }
int mid=(l+r)>>1;
if(R>mid) add(ch[x][1],mid+1,r,L,R,d);
if(L<=mid) add(ch[x][0],l,mid,L,R,d);
} int b[N],tot;
void work(int x,int l,int r){
if(q[x].size()){
tot=0;
for(int i=0;i<v[x].size();i++) b[++tot]=v[x][i].d;
sort(b+1,b+1+tot);
tot=unique(b+1,b+1+tot)-b-1;
for(int i=0;i<v[x].size();i++){
int id=lower_bound(b+1,b+1+tot,v[x][i].d)-b,pre;
pre=(rt[id] ? rt[id] : rt[id-1]);
insert(rt[id]=++cnt2,pre,17,v[x][i].x);
} for(int i=0;i<q[x].size();i++){
if(q[x][i].l>q[x][i].r) continue;
int ll=lower_bound(b+1,b+1+tot,q[x][i].l)-b-1,rr=upper_bound(b+1,b+1+tot,q[x][i].r)-b-1;
if(ll<rr) {
ans[q[x][i].id]=max(ans[q[x][i].id],ask(rt[rr],rt[ll],17,q[x][i].x));
}
} clear(tot);
} if(l==r) return;
int mid=(l+r)>>1;
work(ch[x][0],l,mid); work(ch[x][1],mid+1,r);
} int main()
{
n=read(); m=read();
for(int i=1;i<=n;i++) spi[i]=read(); clear(-1);
for(int i=1;i<=n;i++)
insert(rt[i]=++cnt2,rt[i-1],17,spi[i]); int opt,day=1,ques=0,l,r,d,x;
build(root=++cnt,1,n);
for(int i=0;i<m;i++){
opt=read();
if(opt==0) {
l=read(); x=read();
modify(root,1,n,l,(commo){x,++day});
}
else{
l=read(); r=read(); x=read(); d=read();
add(root,1,n,l,r,(query){x,max(day-d+1,1),day,ques++});
ans[ques-1]=ask(rt[r],rt[l-1],17,x);
}
}
clear(n); work(root,1,n);
for(int i=0;i<ques;i++) printf("%d\n",ans[i]); return 0;
}

[洛谷P4585] [FJOI2015] 火星商店问题的更多相关文章

  1. 洛谷 P4585 [FJOI2015]火星商店问题 解题报告

    P4585 [FJOI2015]火星商店问题 题目描述 火星上的一条商业街里按照商店的编号\(1,2,\dots,n\) ,依次排列着\(n\)个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非 ...

  2. 洛谷 P4585 [FJOI2015]火星商店问题

    (勿看,仅作笔记) bzoj权限题... https://www.luogu.org/problemnew/show/P4585 对于特殊商品,直接可持久化trie处理一下即可 剩下的,想了一段时间c ...

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

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

  4. 【题解】P4585 [FJOI2015]火星商店问题(线段树套Trie树)

    [题解]P4585 [FJOI2015]火星商店问题(线段树套Trie树) 语文没学好不要写省选题面!!!! 题目大意: 有\(n\)个集合,每个集合有个任意时刻都可用的初始元素.现在有\(m\)个操 ...

  5. 【洛谷】P4585 [FJOI2015]火星商店问题

    题解 题目太丧,OJ太没有良心,我永远喜欢LOJ! (TLE报成RE,垃圾洛谷,我永远喜欢LOJ) 好的,平复一下我debug了一上午崩溃的心态= =,写一写这道题的题解 把所有限制去掉,给出一个值, ...

  6. Luogu P4585 [FJOI2015]火星商店问题

    颓文化课作业到很晚写篇博客清醒一下 首先我们仔细阅读并猜测了题意之后,就会想到一个暴力的线段树套可持久化0/1Trie的做法,但是它显然是过不去的 由于最近再做线段树分治的题,我们可以想到用线段树分治 ...

  7. [FJOI2015]火星商店问题

    [FJOI2015]火星商店问题 神仙线段树分治...不过我不会. 这题用线段树套可持久化Trie还是能写的. 常数有点大,洛谷垫底水平. // luogu-judger-enable-o2 #inc ...

  8. 【LG4585】[FJOI2015]火星商店问题

    [LG4585][FJOI2015]火星商店问题 题面 bzoj权限题 洛谷 \(Notice:\) 关于题面的几个比较坑的地方: "一天"不是一个操作,而是有0操作就相当于一天开 ...

  9. [FJOI2015]火星商店问题(线段树分治,可持久化,Trie树)

    [FJOI2015]火星商店问题 前天考了到线段树分治模板题,全场都切了,就我不会QAQ 于是切题无数的Tyher巨巨就告诉我:"你可以去看看火星商店问题,看了你就会了." 第一道 ...

随机推荐

  1. linux 安装一个中断处理

    如果你想实际地"看到"产生的中断, 向硬件设备写不足够; 一个软件处理必须在系统中配 置. 如果 Linux 内核还没有被告知来期待你的中断, 它简单地确认并忽略它. 中断线是一个 ...

  2. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

  3. vue-learning:7-template-v-bind-with-class-and-style

    绑定元素样式的指令v-bind:class 和v-bind:style 在HTML元素结构中,class和style特性(attribute)是非常突出的,可以为元素添加样式属性(property). ...

  4. Numpy 返回数组大小

    import numpy as np a = [[1, 2], [3, 4], [5, 6]] b = np.array(a) len(a) # 3 len(b) # 3 np.size(a) # 3 ...

  5. koa2--04.ejs模板引擎

    首先在项目文件下使用cmd,输入:npm install --save koa-views ejs,将koa-views中间件和ejs模板引擎安装到文件中,并自动写入依赖 接在在index.js文件中 ...

  6. Android7_安卓的知识体系梳理

    最近梳理了一下安卓的知识体系,先构建一个整体性的认知,也作为以后的学习路线的依据. [一.从原理角度出发]1.Activity生命周期和启动模式2.View的事件体系与工作原理3.四大组件的工作过程4 ...

  7. Mac-安装命令一览表

    最近一直在学习Mac,可谓是撞了南墙撞西墙,各种问题需要动手去解决. 今天整理下在笔者Mac下面的各种命令 苹果自带的命令 sudo git ruby node 需要我们安装的命令 brew gem ...

  8. 从头学pytorch(三) 线性回归

    关于什么是线性回归,不多做介绍了.可以参考我以前的博客https://www.cnblogs.com/sdu20112013/p/10186516.html 实现线性回归 分为以下几个部分: 生成数据 ...

  9. spring注解之@Import注解的三种使用方式

    目录 1.@Import注解须知 2.@Import的三种用法 3.@Import注解的三种使用方式总结 @ 1.@Import注解须知 1.@Import只能用在类上 ,@Import通过快速导入的 ...

  10. JAVA字节码文件之常量池

    一.常量池的内容 一个java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是class文件的资源仓库,比如java类中定义的方法与变量信息.常量池中主要存储两类常量:字面量(文本字符 ...