【洛谷4585】[FJOI2015] 火星商店问题(线段树分治)
大致题意: 有\(n\)家店,每个商品有一个标价。每天,都可能有某家商店进货,也可能有某人去购物。一个人在购物时,会于编号在区间\([L_i,R_i]\)的商店里挑选一件进货\(d_i\)天以内的商品使得其标价与\(x_i\)的异或值最大,同时每家店有一个特殊商品在任何时候都可以选择。对于每名购物者求出这个最大异或值。
暴力
一个很暴力的想法,就是线段树套可持久化\(Trie\)树......
但这貌似是过不了的,因此需要优化。
线段树分治
这道题的正解是一个叫做线段树分治的神奇算法。
考虑对于一次询问,它询问的是一段时间区间内的答案。
则我们可以考虑开一棵线段树,然后把每个询问都扔到一个以时间为下标的线段树内的对应区间上。
接下来,考虑离线,在线段树上,用类似于整体二分的思想,维护每一个节点所对应的这段时间内的修改操作。
然后可以参照前面暴力的想法,用一棵可持久化\(Trie\)树。对于每一个节点,我们先清空可持久化\(Trie\)树,再把这个节点的修改对应到可持久化\(Trie\)树上。随后我们枚举询问,求出每个询问所询问的区间后,就可以求出每个询问的答案了。
注意一个询问可能扔到线段树可能会被分成多个,因此答案要取\(max\)。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LN 20
#define max(x,y) ((x)>(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,Et,Qt,ans[N+5];
struct Event {int i,v,t;I bool operator < (Con Event& o) Con {return i<o.i;}}e[N+5];
struct Query {int l,r,v,x,y,t;}q[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
class ChairmanTrie//可持久化Trie
{
private:
#define ST(x) O[rt1].S[x],O[rt2].S[x],v,d-1
int Nt,Vt,Rt[N+5];struct node {int V,S[2];I void Clear() {V=S[0]=S[1]=0;}}O[N*LN<<2];
I void Ins(CI rt1,int& rt2,CI v,CI d)//插入新数
{
O[rt2=++Nt]=O[rt1],++O[rt2].V;if(!~d) return;int t=(v>>d)&1;Ins(ST(t));
}
I int Qry(CI rt1,CI rt2,CI v,CI d)//求最大异或值
{
if(!rt2||!~d) return 0;int t=(v>>d)&1;
return O[O[rt1].S[t^1]].V^O[O[rt2].S[t^1]].V?Qry(ST(t^1))|(1<<d):Qry(ST(t));
}
public:
I void Insert(CI x) {++Vt,Ins(Rt[Vt-1],Rt[Vt],x,LN);}
I int Query(CI l,CI r,CI x) {return Qry(Rt[l-1],Rt[r],x,LN);}
I void Clear() {W(Nt) Rt[Nt--]=0;W(Vt) O[Vt--].Clear();}//清空
}C;
class SegmentTree
{
private:
#define PT CI l=1,CI r=Et,CI rt=1
#define LT l,mid,rt<<1
#define RT mid+1,r,rt<<1|1
#define pb push_back
int s[N+5];Event tl[N+5],tr[N+5];vector<int> P[N<<2];
public:
I void Ins(CI x,CI y,CI p,PT)//扔入询问
{
if(x<=l&&r<=y) return P[rt].pb(p);int mid=l+r>>1;//开vector存储一个节点上的询问
x<=mid&&(Ins(x,y,p,LT),0),y>mid&&(Ins(x,y,p,RT),0);
}
I void Solve(CI x,CI y,PT)//二分求答案
{
if(x>y) return;RI i,t,t1,t2,k=0;int mid=l+r>>1;vector<int>::iterator it;
for(C.Clear(),i=x;i<=y;++i) s[++k]=e[i].i,C.Insert(e[i].v);//将修改对应到可持久化Trie树上
for(it=P[rt].begin();it!=P[rt].end();++it)//枚举这个节点上的询问
t1=upper_bound(s+1,s+k+1,q[*it].l-1)-s,t2=upper_bound(s+1,s+k+1,q[*it].r)-s-1,//求出询问在可持久化Trie树上对应的区间
t=C.Query(t1,t2,q[*it].v),Gmax(ans[q[*it].t],t);//在可持久化Trie树上询问,更新答案
if(l==r) return;for(t1=t2=0,i=x;i<=y;++i) e[i].t<=mid?tl[++t1]=e[i]:tr[++t2]=e[i];
for(i=1;i<=t1;++i) e[x+i-1]=tl[i];for(i=1;i<=t2;++i) e[x+i+t1-1]=tr[i];
Solve(x,x+t1-1,LT),Solve(x+t1,y,RT);//递归操作
}
}S;
int main()
{
RI m,i,op,x;for(F.read(n),F.read(m),i=1;i<=n;++i) F.read(x),C.Insert(x);//对于特殊商品
W(m--) F.read(op),!op?(F.read(e[++Et].i),F.read(e[Et].v),e[Et].t=Et)://读入修改
(
F.read(q[++Qt].l),F.read(q[Qt].r),F.read(q[Qt].v),F.read(x),q[Qt].x=max(Et-x,0)+1,q[Qt].y=Et,//读入询问
ans[Qt]=C.Query(q[Qt].l,q[Qt].r,q[Qt].v),q[Qt].t=Qt//因为特殊商品随时都可以选,因此初始化答案
);
for(i=1;i<=Qt;++i) q[i].x<=q[i].y&&(S.Ins(q[i].x,q[i].y,i),0);sort(e+1,e+Et+1),S.Solve(1,Et);//把询问扔入线段树,离线二分求答案
for(i=1;i<=Qt;++i) F.writeln(ans[i]);return F.clear(),0;//输出答案
}
【洛谷4585】[FJOI2015] 火星商店问题(线段树分治)的更多相关文章
- 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树
正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...
- 【洛谷P4585】 [FJOI2015]火星商店问题 线段树分治+可持久化trie
感觉这个线段树分治和整体二分几乎相同啊~ code: #include <bits/stdc++.h> #define MAX 100300 #define ll long long #d ...
- [FJOI2015]火星商店问题(线段树分治,可持久化,Trie树)
[FJOI2015]火星商店问题 前天考了到线段树分治模板题,全场都切了,就我不会QAQ 于是切题无数的Tyher巨巨就告诉我:"你可以去看看火星商店问题,看了你就会了." 第一道 ...
- BZOJ.4137.[FJOI2015]火星商店问题(线段树分治 可持久化Trie)
BZOJ 洛谷 一直觉得自己非常zz呢.现在看来是真的=-= 注意题意描述有点问题,可以看BZOJ/洛谷讨论. 每个询问有两个限制区间,一是时间限制\([t-d+1,t]\),二是物品限制\([L,R ...
- bzoj 4137 [FJOI2015]火星商店问题——线段树分治+可持久化01trie树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4137 关于可持久化01trie树:https://www.cnblogs.com/LadyL ...
- 【题解】P4585 [FJOI2015]火星商店问题(线段树套Trie树)
[题解]P4585 [FJOI2015]火星商店问题(线段树套Trie树) 语文没学好不要写省选题面!!!! 题目大意: 有\(n\)个集合,每个集合有个任意时刻都可用的初始元素.现在有\(m\)个操 ...
- 洛谷 P4585 [FJOI2015]火星商店问题 解题报告
P4585 [FJOI2015]火星商店问题 题目描述 火星上的一条商业街里按照商店的编号\(1,2,\dots,n\) ,依次排列着\(n\)个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非 ...
- [洛谷P4585] [FJOI2015] 火星商店问题
Description 火星上的一条商业街里按照商店的编号 \(1\),\(2\) ,-,\(n\) ,依次排列着 \(n\) 个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数 \(va ...
- 洛谷 P4585 [FJOI2015]火星商店问题
(勿看,仅作笔记) bzoj权限题... https://www.luogu.org/problemnew/show/P4585 对于特殊商品,直接可持久化trie处理一下即可 剩下的,想了一段时间c ...
- 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)
LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...
随机推荐
- source insight 3 常用设置
总结了一些source insight的一些常用设置,这些设置需求因人而异,自己用的顺手的才是最好的. 1.括号配对高亮“在前括号左侧,后括号左侧”双击鼠标左键,可以选定匹配括号和其中内容(<& ...
- 初识orm
初识orm 一.什么是orm 介绍 ORM: 对象关系映射 将随对象映射成 数据表中的鱼跳跳记录 类--->表名 对象--->记录 对象.属性--->字段 # 演示映射关系 ''' ...
- Cocos2d-x开发教程——《萝莉快跑》
更好的阅读体验请前往<萝莉快跑>开发教程. 配置:win7+Cocos2d-x.2.0.3+VS2012 目标读者:已经了解图形显示.动作.回调函数.定时器的用法. 一.基本知识点 1.动 ...
- 【tf.keras】tensorflow datasets,tfds
一些最常用的数据集如 MNIST.Fashion MNIST.cifar10/100 在 tf.keras.datasets 中就能找到,但对于其它也常用的数据集如 SVHN.Caltech101,t ...
- Bandizip解压压缩软件
上次重装系统以后,特别注意安装软件,在这里提一些比较好的 解压软件:Bandizip 这个是一个免费轻量级的软件,压缩解压速度快,没什么广告,推荐大家在官方下载 Bandizip下载网址 点击下载安装 ...
- java之等待唤醒机制(线程之间的通信)
线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同.比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消 ...
- CSP2019 游记
\(\text{CSP 2019}\) 游记 \[\text{草}\] \[\text{By:Luckyblock}\] \[Day\ -1:\] \(19:00\) 送行饭, 被摁在墙角干了 因为偏 ...
- java之类的构造方法
构造器的特征: 具有和类相同的名称: 不声明返回值的类型: 不能被static.final.synchronized.abstract.native修饰,不能有return语句返回值: 构造器的作用: ...
- IT兄弟连 HTML5教程 HTML5表单 多样的输入类型1
HTML5拥有多个新的表单输入类型,这些新特性提供了更好的输入控制和验证.并不是所有的主浏览器都支持新的input类型,不过我们可以在所有的主浏览器中使用它们,即使不被支持,仍然可以显示为常规的文本域 ...
- Python 爬虫从入门到进阶之路(二)
上一篇文章我们对爬虫有了一个初步认识,本篇文章我们开始学习 Python 爬虫实例. 在 Python 中有很多库可以用来抓取网页,其中内置了 urllib 模块,该模块就能实现我们基本的网页爬取. ...