【题解】FJOI2015火星商店问题
好几天之前做的题目了,一直想写一下博客也没腾出时间来,今天赶紧把坑给填上呼呼呼~
这道题首先如果只考虑每个商店中没有时间限制的物品时,我们只需要使用一棵可持久化trie树来维护区间内的异或最大值即可,这样我们可以把两部分的问题分离开来。
之后我们再考虑有时间限制与编号限制的情况下,该怎样做?无脑做法线段树套trie,直接在对应的区间trie树上贪心,如果该条边的最后更新时间在允许的范围内,说明可以走这条边。虽然这样也可以卡过去(主要在于卡空间),但我们来介绍一种更加妙妙的线段树分治做法。其实我感觉在这题的体现上就是离线版树套树?机房大佬貌似不认可,但我确实是这样觉得哒。
我们考虑在线椴树上的一次区间查询,实际上是将查询的区间分成了log个已经处理好的小区间,分别查询之后再合并达到最终的答案。那么我们可以模拟这个在线段树上分裂区间的操作:
1.如果当前处理的区间(l,r)完全包含于询问区间,我们将这个询问的区间在这一层进行处理。(这样的询问均不再下传,跳过后续步骤)
2.如果询问的区间有涉及(l,mid)的范围,递归左区间处理。
3.如果询问的区间有涉及(mid+1,r)的范围,递归右区间处理。
(本题分治的区间表示时间的范围,可持久化trie负责处理编号的限制)。
这样的复杂度是多少?我们可以分处理trie树与查询的两个方面来分析。处理trie树时,我们插入一个值是log的复杂度,而包含一个修改的总分治区间数也是log个,所以是\(O(nlog^{2}n)\)的复杂度。查询也是log的复杂度,一个查询最多被分别查询 log 次。所以复杂度依然是 \(O(nlog^{2}n)\) 的。
#include <bits/stdc++.h>
using namespace std;
#define maxn 1000000
int n, m, sz, qt, nt, tot, cnt, timer;
int ans[maxn], sum[maxn * ], id[maxn], q[maxn];
int bit[], ch[maxn * ][], num[maxn], root[maxn]; int read()
{
int x = , k = ;
char c; c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} struct ques
{
int l, r, s, t, x;
}Q[maxn]; struct modify
{
int id, val, t;
friend bool operator <(const modify& a, const modify& b)
{ return a.id < b.id; }
}P[maxn], ql[maxn], qr[maxn]; void Ins(int now, int last, int x, int val)
{
if(x < ) return;
bool t = (bit[x] & val);
ch[now][!t] = ch[last][!t]; ch[now][t] = ++ sz;
sum[ch[now][t]] = sum[ch[last][t]] + ;
Ins(ch[now][t], ch[last][t], x - , val);
} int Query(int l, int r, int x, int val)
{
if(l > r || x < ) return ;
int ans = ; bool t = val & bit[x];
if(sum[ch[r][!t]] - sum[ch[l][!t]])
ans = (bit[x] + Query(ch[l][!t], ch[r][!t], x - , val));
else ans = Query(ch[l][t], ch[r][t], x - , val);
return ans;
} int Check(int v)
{
int l = , r = nt, ret = ;
while(l <= r)
{
int mid = (l + r) >> ;
if(num[mid] <= v) ret = mid, l = mid + ;
else r = mid - ;
}
return ret;
} void Work(int l, int r)
{
sz = , nt = ;
for(int i = l; i <= r; i ++)
{
nt ++; root[nt] = ++ sz;
Ins(root[nt], root[nt - ], , P[i].val);
num[nt] = P[i].id;
}
for(int i = ; i <= qt; i ++)
{
int l = Check(Q[q[i]].l - ), r = Check(Q[q[i]].r);
ans[q[i]] = max(ans[q[i]], Query(root[l], root[r], , Q[q[i]].x));
}
} void Divide(int l, int r, int L, int R, int pres)
{
if(l > r || !pres) return;
int mid = (L + R) >> ; qt = ;
for(int i = ; i <= pres; i ++)
if(Q[id[i]].s <= L && R <= Q[id[i]].t) q[++ qt] = id[i];
Work(l, r); if(L == R) return;
int ll = , rr = ;
for(int i = l; i <= r; i ++)
{
if(P[i].t <= mid) ql[++ ll] = P[i];
else qr[++ rr] = P[i];
}
for(int i = ; i <= ll; i ++) P[i + l - ] = ql[i];
for(int i = ; i <= rr; i ++) P[i + l + ll - ] = qr[i]; int ind = ;
for(int i = ; i <= pres; i ++)
{
if(Q[id[i]].s <= L && R <= Q[id[i]].t) continue;
if(Q[id[i]].s <= mid) swap(id[i], id[++ ind]);
}
Divide(l, l + ll - , L, mid, ind);
ind = ;
for(int i = ; i <= pres; i ++)
{
if(Q[id[i]].s <= L && R <= Q[id[i]].t) continue;
if(Q[id[i]].t > mid) swap(id[i], id[++ ind]);
}
Divide(l + ll, r, mid + , R, ind);
} int main()
{
bit[] = ; for(int i = ; i <= ; i ++) bit[i] = bit[i - ] << ;
n = read(), m = read();
for(int i = ; i <= n; i ++) root[i] = ++ sz, Ins(root[i], root[i - ], , read());
for(int i = ; i <= m; i ++)
{
int opt = read();
if(!opt)
{
++ timer; P[++ tot].id = read();
P[tot].val = read(); P[tot].t = timer;
}
else
{
Q[++ cnt].l = read(); Q[cnt].r = read();
Q[cnt].x = read(); int d = read();
Q[cnt].s = max(timer - d, ) + ; Q[cnt].t = timer;
ans[cnt] = Query(root[Q[cnt].l - ], root[Q[cnt].r], , Q[cnt].x);
}
}
sort(P + , P + + tot);
for(int i = ; i <= cnt; i ++) id[i] = i;
Divide(, tot, , timer, cnt);
for(int i = ; i <= cnt; i ++) printf("%d\n", ans[i]);
return ;
}
【题解】FJOI2015火星商店问题的更多相关文章
- 【题解】P4585 [FJOI2015]火星商店问题(线段树套Trie树)
[题解]P4585 [FJOI2015]火星商店问题(线段树套Trie树) 语文没学好不要写省选题面!!!! 题目大意: 有\(n\)个集合,每个集合有个任意时刻都可用的初始元素.现在有\(m\)个操 ...
- 【LG4585】[FJOI2015]火星商店问题
[LG4585][FJOI2015]火星商店问题 题面 bzoj权限题 洛谷 \(Notice:\) 关于题面的几个比较坑的地方: "一天"不是一个操作,而是有0操作就相当于一天开 ...
- [FJOI2015]火星商店问题
[FJOI2015]火星商店问题 神仙线段树分治...不过我不会. 这题用线段树套可持久化Trie还是能写的. 常数有点大,洛谷垫底水平. // luogu-judger-enable-o2 #inc ...
- 洛谷 P4585 [FJOI2015]火星商店问题 解题报告
P4585 [FJOI2015]火星商店问题 题目描述 火星上的一条商业街里按照商店的编号\(1,2,\dots,n\) ,依次排列着\(n\)个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非 ...
- [FJOI2015]火星商店问题(线段树分治,可持久化,Trie树)
[FJOI2015]火星商店问题 前天考了到线段树分治模板题,全场都切了,就我不会QAQ 于是切题无数的Tyher巨巨就告诉我:"你可以去看看火星商店问题,看了你就会了." 第一道 ...
- [FJOI2015]火星商店问题(分治+可持久化)
题目描述 火星上的一条商业街里按照商店的编号1,2 ,…,n ,依次排列着n个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数val来标价.每个商店每天都有可能进一些新商品,其标价可能与已 ...
- BZOJ4137 & 洛谷4585:[FJOI2015]火星商店问题
https://www.lydsy.com/JudgeOnline/problem.php?id=4137 https://www.luogu.org/problemnew/show/P4585 火星 ...
- 【bzoj4137】[FJOI2015]火星商店问题
*题目描述: 火星上的一条商业街里按照商店的编号1,2 ,…,n ,依次排列着n个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数val来标价.每个商店每天都有可能进一些新商品,其标价可能 ...
- 【洛谷】P4585 [FJOI2015]火星商店问题
题解 题目太丧,OJ太没有良心,我永远喜欢LOJ! (TLE报成RE,垃圾洛谷,我永远喜欢LOJ) 好的,平复一下我debug了一上午崩溃的心态= =,写一写这道题的题解 把所有限制去掉,给出一个值, ...
随机推荐
- STM32的System memory
Main Flash memory 是STM32内置的Flash,一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序. System memory 从系统存储器 ...
- JS日期转换
用js将从后台得到的时间戳(毫秒数)转换为想要的日期格式 得到后台从数据库中拿到的数据我们希望格式是 2016年10月25日 17时37分30秒 或者 2016/10/25 17:37:30 然而我们 ...
- 利用反射获取Model值
public ActionResult Base(UserModel Model) { Model.Tel = string.Format("{0}-{1}", Model.Are ...
- golang 仿python pack/unpack
写得不完善也不完美 尤其是高低位转换那(go和c 二进制高地位相反 需要转换,还有go int转[]byte长度是4位),希望牛人看后指导一下 项目需要通过socket调取 客户端是go ,服务器端是 ...
- Qt-QML-Repeater-导航条
上篇文章中,我写了一个自己的Button,也就是美化了一下QML自带的Button 就是上面的这个,剩下的就是放三张图片在上面就可以了,当然了,这个Button在后期,还是会加入更让多的美化,比如,可 ...
- RabbitMQ基础教程之使用进阶篇
RabbitMQ基础教程之使用进阶篇 相关博文,推荐查看: RabbitMq基础教程之安装与测试 RabbitMq基础教程之基本概念 RabbitMQ基础教程之基本使用篇 I. 背景 前一篇基本使用篇 ...
- windows环境下jmeter生成测试报告
1.要求 jmeter需要在3.0版本以上 jdk1.7以上 需要准备脚本文件,即jmx文件 2.进入cmd界面 3.进入jmeter的bin目录 cd:\xxxx\apache-jmeter-4.0 ...
- 聊一聊session
最近从上家公司离职了,到了一家新公司,这几天一直在了解他们的项目,所以我自己的那个小项目也暂时搁浅了.. 今天差不多把他们的项目了解了,来院子写写我在这里边遇到的问题,影响最深刻的是seesion的. ...
- js如何使浏览器允许脚本异步加载
js如何使浏览器允许脚本异步加载 如果脚本体积很大,下载和执行的时间就会很长,因此造成浏览器堵塞,用户会感觉到浏览器“卡死”了,没有任何响应.这显然是很不好的体验,所以浏览器允许脚本异步加载,下面就是 ...
- js经典试题之w3规范系列
js经典试题之w3规范系列 1:w3c 制定的 javascript 标准事件模型的正确的顺序? 答案:事件捕获->事件处理->事件冒泡 解析:先事件捕获从windows > doc ...