UOJ #218. 【UNR #1】火车管理】的更多相关文章

很简单 用一个线段树维护 1.答案 2.当前栈顶是什么时候push进来的 然后用一棵以时间为版本的可持久化线段树维护每个操作之后第一个覆盖到他的操作是哪个 就可以了 询问直接在线段树上询问,修改在两棵树上分别修改即可 调一年 //wls niubi! #include<bits/stdc++.h> #define LL long long using namespace std; inline int read() { ,f = ;char ch = getchar(); for(;!isdi…
[UNR #1]火车管理(主席树) 好好的代码被 \(extra\ test\) 卡常了...我就放一个目前最快的版本吧... 题意简化: 有 \(n\) 个栈,\(m\) 次操作. 将 \(x\) 压入 \([l,r]\) 的栈中 将 \(l\) 的栈顶弹出 询问 \([l,r]\) 栈顶的和 \(n,m\leq 5\times 10^5\) 虽然最优解是神仙二叉树,我只会主席树的解法... 显然 \(1,3\) 操作用一棵线段树就够了,\(2\) 操作需要另外一棵主席树,并且在历史版本上修改…
「UOJ218」火车管理 解题思路:观察发现,在弹出 \(x\) 之前,它前面这个元素都是保持不变的,所以可以用一棵可持久化线段树维护每一个栈顶元素的插入时间,每次找到当前时间\(-1\) 的版本就可以查到栈顶,另外用一棵线段树维护区间答案即可,复杂度 \(O(m\log n)\) /*program by mangoyang*/ #include <bits/stdc++.h> #define inf (0x7f7f7f7f) #define Max(a, b) ((a) > (b)…
[UOJ#128][BZOJ4196][Noi2015]软件包管理器 试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器. 你决定设计你自己的软件包管理器.…
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html 题解 如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖.区间求和的线段树上完成这个问题. 于是本题的重点转到了如何求新的栈顶. 考虑用一个主席树维护一下每一个时刻每一个位置的栈顶元素的进栈时间,那么新的栈顶就是 当前位置栈顶的进栈时间-1 这时候的栈顶元素,然后这个东西也可以用我们维护的进栈时间来得到,所以我们只需要弄一个支持区间覆盖单点查询历史版本的主席树:这…
Description Solution 实际上添加问题就是一个线段树区间覆盖问题,打标记就好 对于弹栈操作比较难搞,实际上也就是一个历史查询,我们不需要保存栈中的每一个元素,我们通过查找历史状态就可以了 这样用主席树维护复杂度是 \(O(n*logn)\) 的 具体是这样的: 假设我们要弹出位置 \(x\) 的栈顶元素,那么在线段树中维护一个值 \(t\),表示最近的一次修改是 \(t\) 时刻 那么上上次修改就可以通过查询 \(t-1\) 时刻的 \(t\) 找出,相当于保存了一个前驱 用主…
Code: #include<bits/stdc++.h> #define maxn 500005 using namespace std; int n,Q,ty,lastans=0; int rt[maxn], tim[maxn], lp[maxn], tp[maxn]; void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r&q…
http://uoj.ac/problem/218 思路:建立一个可持久化线段树,代表这个位置的火车是哪辆,然后再弄一个线段树维护答案. 如果询问,直接询问线段树. 如果区间压入,直接在主席树上面压入,然后更新线段树答案 如果弹出,那么直接找主席树当前位之前的火车是那辆,然后修改线段树答案,再修改当前主席树答案. 改题的时候蜜汁错误.. #include<cstdio> #include<cmath> #include<cstring> #include<iost…
来自FallDream的博客,未经允许,请勿转载,谢谢. 题面 考虑用可持久化线段树直接维护每个点在不同时刻,第一辆车的编号. 这样3操作就变成了区间赋值,1操作变成区间和 2操作的话,只需要查询一下现在这辆车的编号,再到历史版本去查一下上一辆车的编号就行了. #include<iostream> #include<cstdio> #define MN 500000 using namespace std; inline int read() { ,f=;char ch=getch…
用可持久化线段树维护每个站的第一辆车和每个站的前一次更新的位置即可. #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> #define maxn 500005 using namespace std; inline int read() { ,f=;char ch=get…