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

  这道题首先如果只考虑每个商店中没有时间限制的物品时,我们只需要使用一棵可持久化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. create-react-app创建react项目 css模块化处理

    用的css预处理器用sass,其他大同小异. 用create-react-app创建项目,执行npm run eject弹出配置文件(此操作不可逆): 配置sass,用的最新的CRA,webpack4 ...

  2. Fiddler使用总结(三)

    我们知道Fiddler是位于客户端和服务器之间的代理,它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据.设置断点.调试web应用.修改请求的数据,甚至可以修改 ...

  3. Django - day01 快速回忆ORM操作

    Django - day01 Model的增删改查找 得益于Django的ORM模型,用面向对象的思想来操作数据库使得数据库的操作一切变得简洁了很多. 0. 建表 在应用下的models.py中建立一 ...

  4. 【转】从零开始学习Skynet_examples研究

    转自 http://blog.csdn.net/mr_virus/article/details/52330193 一.编译Skynet: 1.用ubuntu15.10直接 make linux 编译 ...

  5. beego 笔记

    1.开发文档 https://beego.me/docs/intro/ 2.bee run projectname demo controller package autoscaler import ...

  6. python常用命令—ipython3环境下获取某个文件夹下的文件列表

    import os os.listdir('文件夹路径')

  7. centos+nginx+redmine+gitosis安装指南

    说明 这篇文章我现在的主要目的是记录自己安装redmine和gitosis的过程,可能写的有些糙,请各位读者见谅.我会在后面的时间里逐渐完善细节.但我想,这已经是网上迄今为止国内最详细的nginx+r ...

  8. su和sudo的使用

    用于用户身份切换 一.su 命令形式 代表内容 su 切换为root,以non-login shell的方式 su - 切换为root,以login shell的方式 su -l 账号 切换为“账号” ...

  9. qwe

    这次作业我负责的部分是把爬取完的聊天记录经行数据挖掘以及经行各种普通过滤高级过滤等. 运行截图如下: 数据分为四部分:账户名.qq/邮箱.包含关键词的发言次数.包含关键词的发言字数. 遇到的困难及解决 ...

  10. java—连连看GUI

    1.连连看棋盘图形化 package Link; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; impo ...