[FJOI2015]火星商店问题(线段树分治,可持久化,Trie树)
[FJOI2015]火星商店问题
前天考了到线段树分治模板题,全场都切了,就我不会QAQ
于是切题无数的Tyher巨巨就告诉我:"你可以去看看火星商店问题,看了你就会了."
第一道线段树分治题,看了yyb博客,学习了一波.
其实线段树分治就是对操作的时间分治.
对线段树每个节点开一个\(vector\),把询问的区间(时间的区间)看成一段一段放到线段树的\(vector\)里面存着.
注意到修改会延续到最后一刻,所以修改只是左端点不一样而已,相当于一个后缀.
把修改按照位置排序(这个时候时间是乱序的),接着仿照线段树的形式按时间分治,在\(mid\)之前的修改,就扔到左边的数组里递归,否则就扔到右边的子树.这样就除掉了时间这一维的限制.
那么空间这一维,就用一个可持久化trie树来维护,\(r\)和\(l-1\)的对应的字典树前缀和相减就是区间的字典树.注意最开始修改要按照商店编号排序,这样按照时间分拣之后它的商店编号依然是有序的,你不妨把这些有修改的商店之间的其他商店都忽略掉,一个修改挨着一个修改地构建主席树,保证了时间复杂度.
还有一个值得注意的问题,就是当把点加到可持久化字典树里的时候,要重新从当前左端点构出字典树(相当于清空这棵可持久化字典树,假如这个询问对应的答案是当前区间之前的某次修改加入的值,那么这个询问也一定会被丢到对应的线段树节点上计算,所以不用担心之前的修改会影响询问的答案)这样可以避免撤销带来的常数.
再按照trie树找异或最大值的方法来找答案,一个询问会被放到线段树的多个节点上(会被分成很多段时间),所以答案要取\(max\).
注意线段树上的是修改时间,字典树是按照空间构建的.这个很重要,总是写着写着就忘了...
时间复杂度\(O(nlog^2n)\),线段树分治和trie树\(nlogn\),字典树\(logn\)
#include<bits/stdc++.h>
#define maxn 100005
#define mid ((l+r)>>1)
#define rc ((rt<<1)|1)
#define lc (rt<<1)
using namespace std;
int gi()
{
char c;int x,sign=1;
while((c=getchar())>'9'||c<'0')if(c=='-')sign=-1;
x=c-'0';while((c=getchar())>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0';
return x*sign;
}
int n,m,cnt1,cnt2,tot,top;
int rt[maxn],ans[maxn],st[maxn];
int ch[maxn*20][2],sz[maxn*20];
vector<int> a[maxn];
struct guest{int l,r,L,R,x;}p[maxn];
struct buy{int s,v,t;}q[maxn],t1[maxn],t2[maxn];
bool cmp(const buy x,const buy y){return x.s<y.s;}
void insert(int &x,int u,int w)
{
int now;now=x=++tot;
for(int i=17;i>=0;i--)
{
bool d=w&(1<<i);
ch[now][d^1]=ch[u][d^1];ch[now][d]=++tot;
now=ch[now][d];u=ch[u][d];
sz[now]=sz[u]+1;
}
}
int query(int l,int r,int w)
{
int res=0;
for(int i=17;i>=0;i--)
{
bool d=w&(1<<i);
if(sz[ch[r][d^1]]-sz[ch[l][d^1]]>0)
l=ch[l][d^1],r=ch[r][d^1],res+=(1<<i);
else l=ch[l][d],r=ch[r][d];
}
return res;
}
void update(int rt,int l,int r,int L,int R,int x)
{
if(L>R||r<L||l>R)return ;
if(L<=l&&r<=R){a[rt].push_back(x);return;}
update(lc,l,mid,L,R,x);update(rc,mid+1,r,L,R,x);
}
void calc(int x,int L,int R)
{
top=tot=0;
for(int i=L;i<=R;i++)
{
st[++top]=q[i].s;
insert(rt[top],rt[top-1],q[i].v);
}
for(int i=0,sz=a[x].size();i<sz;i++)
{
int k=a[x][i],t;
int l=upper_bound(st+1,st+1+top,p[k].l-1)-st-1;
int r=upper_bound(st+1,st+1+top,p[k].r)-st-1;
ans[k]=max(ans[k],t=query(rt[l],rt[r],p[k].x));
//cout<<x<<" "<<k<<" "<<t<<endl;
}
}
void divide(int rt,int l,int r,int L,int R)//按时间分治
{
if(L>R)return;
int cn1=0,cn2=0;
calc(rt,L,R);
if(l==r)return;
for(int i=L;i<=R;i++)//修改的区间右端点都是cnt1,相当于影响到之后的时间
if(q[i].t<=mid)t1[++cn1]=q[i];
else t2[++cn2]=q[i];
for(int i=1;i<=cn1;i++)q[i+L-1]=t1[i];//左端点在mid左边的放在左区间
for(int i=1;i<=cn2;i++)q[i+L-1+cn1]=t2[i];//否则放右边
divide(lc,l,mid,L,L+cn1-1);
divide(rc,mid+1,r,L+cn1,R);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)insert(rt[i],rt[i-1],gi());
for(int i=1,ty,l,r,x,d,s,v;i<=m;i++)
{
ty=gi();
if(!ty)s=gi(),v=gi(),q[++cnt1]=(buy){s,v,cnt1};//起点,价格,时间
else
{
l=gi(),r=gi(),x=gi(),d=gi();
ans[++cnt2]=query(rt[l-1],rt[r],x);
p[cnt2]=(guest){l,r,max(1,cnt1-d+1),cnt1,x};
//商店左端点,商店右端点,开始时间,结束时间,喜好密码
}
}
for(int i=1;i<=cnt2;i++)update(1,1,cnt1,p[i].L,p[i].R,i);
sort(q+1,q+1+cnt1,cmp);//按照商店编号排序
divide(1,1,cnt1,1,cnt1);
for(int i=1;i<=cnt2;i++)printf("%d\n",ans[i]);
return 0;
}
[FJOI2015]火星商店问题(线段树分治,可持久化,Trie树)的更多相关文章
- bzoj 4137 [FJOI2015]火星商店问题【CDQ分治+可持久化trie】
其实我不太清楚这个应该叫CDQ分治还是整体二分 参考:http://blog.csdn.net/lvzelong2014/article/details/78688727 一眼做法是线段树套可持久化t ...
- 【题解】P4585 [FJOI2015]火星商店问题(线段树套Trie树)
[题解]P4585 [FJOI2015]火星商店问题(线段树套Trie树) 语文没学好不要写省选题面!!!! 题目大意: 有\(n\)个集合,每个集合有个任意时刻都可用的初始元素.现在有\(m\)个操 ...
- bzoj 4137 [FJOI2015]火星商店问题——线段树分治+可持久化01trie树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4137 关于可持久化01trie树:https://www.cnblogs.com/LadyL ...
- [FJOI2015]火星商店问题(线段树分治+可持久化Trie)
重新写一年前抄题解的那题,当时我啥都不会只是Ctrl+C,Ctrl+V写过的题,今天重新写一遍. 题解: 不会线段树分治,还是学一下这东西吧,这是我的第一道线段树分治. 首先对于特殊商品,可以直接可持 ...
- BZOJ.4137.[FJOI2015]火星商店问题(线段树分治 可持久化Trie)
BZOJ 洛谷 一直觉得自己非常zz呢.现在看来是真的=-= 注意题意描述有点问题,可以看BZOJ/洛谷讨论. 每个询问有两个限制区间,一是时间限制\([t-d+1,t]\),二是物品限制\([L,R ...
- 【洛谷P4585】 [FJOI2015]火星商店问题 线段树分治+可持久化trie
感觉这个线段树分治和整体二分几乎相同啊~ code: #include <bits/stdc++.h> #define MAX 100300 #define ll long long #d ...
- 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树
正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...
- 【洛谷4585】[FJOI2015] 火星商店问题(线段树分治)
点此看题面 大致题意: 有\(n\)家店,每个商品有一个标价.每天,都可能有某家商店进货,也可能有某人去购物.一个人在购物时,会于编号在区间\([L_i,R_i]\)的商店里挑选一件进货\(d_i\) ...
- 【洛谷】P4585 [FJOI2015]火星商店问题
题解 题目太丧,OJ太没有良心,我永远喜欢LOJ! (TLE报成RE,垃圾洛谷,我永远喜欢LOJ) 好的,平复一下我debug了一上午崩溃的心态= =,写一写这道题的题解 把所有限制去掉,给出一个值, ...
随机推荐
- Netty-新连接接入源码解读
本片博文来看Netty的服务端是如何处理新连接接入问题的 什么是新连接接入?以及新连接接入前,Netty处于什么状态 netty的服务端NioServerSocketChannel初始化,注册在Bos ...
- SpringBoot基于数据库实现简单的分布式锁
本文介绍SpringBoot基于数据库实现简单的分布式锁. 1.简介 分布式锁的方式有很多种,通常方案有: 基于mysql数据库 基于redis 基于ZooKeeper 网上的实现方式有很多,本文主要 ...
- python基础知识三 字典-dict + 菜中菜
3.7字典:dict+菜中菜 1.简介 无序,可修改,用于存储数据,大量,比列表快,将数据和数据之间关联 定义:dict1 = {'cx':10,'liwenhu':80,'zhangyu': ...
- 洛谷P4995 跳跳!题解
求关注,求赞,求评论QAQ 题目:https://www.luogu.org/problemnew/show/P4995 简单描述一下吧,就是说有n块石头,起始可以跳到任何一块上面,接着也是,只不过每 ...
- 运用KeyCode在浏览器中按WASD使图形运动
如何实现在浏览器中按WASD四个键使图形上下左右运动呢? 其实很简单,用keyCode方法就可以实现了. 先放个div在html中: <div id="ball" style ...
- 个人永久性免费-Excel催化剂功能第37波-把Sqlserver的强大分析函数拿到Excel中用
本人一直钟情于使用Sqlserver数据库的一大原因是其提供了非常好用.高效的数据分析函数(窗口函数),可以在做数据清洗和数据分析场合等多个场景使用.只需简单的一个函数即可做出常规SQL语句很难以实现 ...
- C#3.0新增功能09 LINQ 标准查询运算符 02 查询表达式语法
连载目录 [已更新最新开发文章,点击查看详细] 某些使用更频繁的标准查询运算符具有专用的 C# 语言关键字语法,使用这些语法可以在查询表达式中调用这些运算符. 查询表达式是比基于方法的等效项更具 ...
- Apache Httpd 启用重定向 rewrite
1.启用模块 由:#LoadModule rewrite_module modules/mod_rewrite.so 更改为:LoadModule rewrite_module modules/mod ...
- WebGL中深度碰撞方法总结
z-fighting问题是三维渲染中常见的问题,本文根据实际工作中遇到的一些场景,进行了系统的总结 一个实际工作中的问题 当两个面离得太近就会发生深度碰撞问题,比如: 遇到深度检测问题,最重要的是先搞 ...
- 15款好用超赞的chrome插件, 开发者们的必备~
今天推荐一波Chrome插件干货.这些插件带给我开发效率上的提升.所以在这里整理一下,分享给朋友们. 作为一名程序开发者,推荐一波常用的chrome插件,用了就舍不得丢,包括免费FQ工具,github ...