好几天之前做的题目了,一直想写一下博客也没腾出时间来,今天赶紧把坑给填上呼呼呼~

  这道题首先如果只考虑每个商店中没有时间限制的物品时,我们只需要使用一棵可持久化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火星商店问题的更多相关文章

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

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

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

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

  3. [FJOI2015]火星商店问题

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

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

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

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

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

  6. [FJOI2015]火星商店问题(分治+可持久化)

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

  7. BZOJ4137 & 洛谷4585:[FJOI2015]火星商店问题

    https://www.lydsy.com/JudgeOnline/problem.php?id=4137 https://www.luogu.org/problemnew/show/P4585 火星 ...

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

    *题目描述: 火星上的一条商业街里按照商店的编号1,2 ,…,n ,依次排列着n个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数val来标价.每个商店每天都有可能进一些新商品,其标价可能 ...

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

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

随机推荐

  1. CF 314 E. Sereja and Squares

    E. Sereja and Squares http://codeforces.com/contest/314/problem/E 题意: 给你一个擦去了部分左括号和全部右括号的括号序列,括号有25种 ...

  2. ONTAK 2010 aut

    Autostrady https://szkopul.edu.pl/problemset/problem/f2dSBM7JteWHqtmVejMWe1bW/site/?key=statement 题意 ...

  3. 封装一个Automapper单例

    public class DataModule : IModule { public void Configure(IMapperConfigurationExpression cfg) { //cf ...

  4. 无法嵌入互操作类型“ADOX.CatalogClass”。请改用适用的接口。

    编译环境:vs2013 系统报错:无法嵌入互操作类型"ADOX.CatalogClass".请改用适用的接口. 解决方法:选中项目中引入的dll(本例中为Microsoft ADO ...

  5. Error -26377: No match found for the requested parameter

    Error -26377: No match found for the requested parameter

  6. 初学Direct X(8) ——碰撞检测

    初学Direct X(8) --碰撞检测 真正让一个游戏鹤立鸡群的是程序对碰撞的响应有多好,这里介绍两种检测的方法: 1) 基于边框的碰撞检测 2) 基于距离的碰撞检测 1. 基于边框的碰撞检测 1. ...

  7. VMware SDK使用指南

    刚开始用VMware官方推荐的SDK,真的是又臭又长,代码结构不清晰,易读性差.后来VMware的同学给推荐了一款开源的SDK,一上手感觉工作效率提高了100倍!推荐大家使用~. 该SDK对VMwar ...

  8. 硬盘基础知识&&分区

    学习记录的笔记,虽然毫无章法 硬盘基础知识 磁盘的物理组成 如下图所示: 有关磁盘物理知识的详细介绍请看硬盘的存储原理和内部架构这篇博文 硬盘接口类型 IDE SATA SCSI SAS 光纤通道 I ...

  9. jQuery 对象 与 原生 DOM 对象 相互转换

    区别 jQuery 选择器得到的 jQuery对象 和 原生JS 中的document.getElementById() document.querySelector取得的 DOM对象 是两种不同类型 ...

  10. django request bug

    bug描述:django请求request接收数据时,如果参数中包含分号时,会导致分号后面的消息丢失. 比如前台js调用代码 $.post('/get_params', { "A" ...