uoj218_火车管理
题意
\(n\)个位置,每个位置一个栈,三种操作,询问区间栈顶的和,区间入栈某个数,单点出栈某个数。
分析
- 用一个线段树来维护栈顶的和,区间(单点)更新和区间询问。
- 用一个主席树来维护每个位置最新一次入栈的时间,即主席树存的是时间,然后取出的时间也能作为主席树的下标来访问对应时间的版本。
- 因此区间入栈的时候区间更新线段树和区间更新主席树。
- 单点出栈时,先查询这个位置栈顶元素的入栈时间,然后再用这个时间的上一个版本的主席树查询栈顶下一个元素的入栈时间,根据入栈时间可以知道入栈的元素,然后由于栈顶已经出栈,所以新的栈顶就是该元素,单点更新线段树和主席树。
代码
#include <bits/stdc++.h>
#define ls i<<1
#define rs i<<1|1
#define mid (l+r)/2
using namespace std;
typedef long long ll;
const int N=8e5+50;
int n,m,ty,o,l1,r1,x[N];
struct ST{
//lz:区间赋值标记 sum:区间和
ll lz[N*4],sum[N*4];
void pushup(int i){
sum[i]=sum[ls]+sum[rs];
}
void pushdown(int i,int l,int r){
if(lz[i]){
lz[ls]=lz[i];
lz[rs]=lz[i];
sum[ls]=(mid-l+1)*lz[i];
sum[rs]=(r-mid)*lz[i];
lz[i]=0;
}
}
void update(int i,int l,int r,int ql,int qr,int v){
if(ql<=l && qr>=r){
lz[i]=v;
sum[i]=1ll*(r-l+1)*v;
return;
}
pushdown(i,l,r);
if(ql<=mid){
update(ls,l,mid,ql,qr,v);
}
if(qr>mid){
update(rs,mid+1,r,ql,qr,v);
}
pushup(i);
}
ll query(int i,int l,int r,int ql,int qr){
if(ql<=l && qr>=r){
return sum[i];
}
pushdown(i,l,r);
ll ans=0;
if(ql<=mid){
ans+=query(ls,l,mid,ql,qr);
}
if(qr>mid){
ans+=query(rs,mid+1,r,ql,qr);
}
return ans;
}
}st;
int tr[N];
struct CT{
int tot=0,tim[N*50],lr[N*50],rr[N*50];
int update(int pre,int l,int r,int ql,int qr,int t){
int rt=++tot;
tim[rt]=t;
lr[rt]=lr[pre];
rr[rt]=rr[pre];
if(ql<=l && qr>=r){
lr[rt]=rr[rt]=(l==r?0:rt);
}else{
if(ql<=mid){
lr[rt]=update(lr[pre],l,mid,ql,qr,t);
}
if(qr>mid){
rr[rt]=update(rr[pre],mid+1,r,ql,qr,t);
}
}
return rt;
}
int query(int i,int l,int r,int v){
if(l==r && l==v){
return tim[i];
}
if(v<=mid){
return query(lr[i],l,mid,v);
}else{
return query(rr[i],mid+1,r,v);
}
}
}ct;
int dec(int l1,int lst){
return (l1+lst*ty)%n+1;
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&m,&ty);
ll lst=0;
for(int t=1;t<=m;t++){
scanf("%d",&o);
tr[t]=tr[t-1];
if(o==1){
scanf("%d%d",&l1,&r1);
l1=dec(l1,lst);
r1=dec(r1,lst);
int l=min(l1,r1);
int r=max(l1,r1);
//直接查询线段树区间和
lst=st.query(1,1,n,l,r);
printf("%lld\n",lst);
}else if(o==2){
scanf("%d",&l1);
int l=dec(l1,lst);
//查询l这个位置最新插入的时间
int tm=ct.query(tr[t],1,n,l);
//查询再前一个插入时间,即将最新插入出栈
int pt=ct.query(tr[tm-1],1,n,l);
//线段树单点修改为上一个版本
st.update(1,1,n,l,l,x[pt]);
//主席树对当前最新版本单点修改l位置的插入时间
tr[t]=ct.update(tr[t],1,n,l,l,pt);
}else if(o==3){
scanf("%d%d%d",&l1,&r1,&x[t]);
l1=dec(l1,lst);
r1=dec(r1,lst);
int l=min(l1,r1);
int r=max(l1,r1);
//线段树区间更新
st.update(1,1,n,l,r,x[t]);
//前面已经有tr[t]=tr[t-1] 无论更不更新都复制一个新版本
//主席树区间更新
tr[t]=ct.update(tr[t],1,n,l,r,t);
}
}
return 0;
}
uoj218_火车管理的更多相关文章
- 【UNR #1】火车管理(主席树)
[UNR #1]火车管理(主席树) 好好的代码被 \(extra\ test\) 卡常了...我就放一个目前最快的版本吧... 题意简化: 有 \(n\) 个栈,\(m\) 次操作. 将 \(x\) ...
- 「UOJ218」火车管理
「UOJ218」火车管理 解题思路:观察发现,在弹出 \(x\) 之前,它前面这个元素都是保持不变的,所以可以用一棵可持久化线段树维护每一个栈顶元素的插入时间,每次找到当前时间\(-1\) 的版本就可 ...
- 【UNR #1】火车管理
题目描述 uoj 旗下有一个火车站,用来管理属于 uoj 的小火车. 火车站一共有 nn 条编号为 1,…,n1,…,n 的,只有一端的用来存放小火车的铁路,由于小火车特殊的构造,每条铁路可以停放无数 ...
- UOJ 218 火车管理
http://uoj.ac/problem/218 思路:建立一个可持久化线段树,代表这个位置的火车是哪辆,然后再弄一个线段树维护答案. 如果询问,直接询问线段树. 如果区间压入,直接在主席树上面压入 ...
- 【UOJ UNR #1】火车管理
来自FallDream的博客,未经允许,请勿转载,谢谢. 题面 考虑用可持久化线段树直接维护每个点在不同时刻,第一辆车的编号. 这样3操作就变成了区间赋值,1操作变成区间和 2操作的话,只需要查询一下 ...
- UOJ#218. 【UNR #1】火车管理 线段树 主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html 题解 如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖.区间求和 ...
- UOJ #218. 【UNR #1】火车管理
Description Solution 实际上添加问题就是一个线段树区间覆盖问题,打标记就好 对于弹栈操作比较难搞,实际上也就是一个历史查询,我们不需要保存栈中的每一个元素,我们通过查找历史状态就可 ...
- [UOJ218]火车管理
建一棵答案线段树存栈顶值,两棵可持久化线段树分别存栈顶值和栈顶元素入栈时间 询问就直接在答案线段树上查,弹栈就用入栈时间在对应版本的可持久化线段树上查询即可,修改就是可持久化线段树的区间覆盖 以前一直 ...
- 【UOJ UNR #1】火车管理 可持久化线段树
用可持久化线段树维护每个站的第一辆车和每个站的前一次更新的位置即可. #include<iostream> #include<cstring> #include<cstd ...
随机推荐
- python3基础: 元组tuple、 列表list、 字典dict、集合set。 迭代器、生成器
一.元组: tuple Python 的元组与列表类似,不同之处在于元组的元素不能修改. 元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组 tup2 = (111, 22, 33, ...
- 成功解决internal/modules/cjs/loader.js:596 throw err; ^ Error: Cannot find module 'minimatch'
成功解决internal/modules/cjs/loader.js:596 throw err; ^ Error: Cannot find module 'minimatch' 解决办法 npm i ...
- PHP 判断当前日期是否是法定节假日或者休息日 (原)
//判断日期是不是节假日或者双休日接口 @param time [时间(时间戳或者Y-m-d都可)] public function get_type_by_date(){ $t = $_GET['t ...
- IDEA 无法显示项目目录结构解决
不要去网上看什么乱七八糟的骚教程,一点用都没有.直接按下列步骤操作: 1. 关闭IDEA, 2. 然后删除项目文件夹下的.idea文件夹3. 重新用IDEA工具打开项目
- 关于慕课网《使用vue2.0实现购物车和地址选配功能》的总结
视频学习网址:http://www.imooc.com/learn/796 源码打包:https://codeload.github.com/fachaoshao/Vue-ShoppingCart/z ...
- 【Spark机器学习速成宝典】模型篇08保序回归【Isotonic Regression】(Python版)
目录 保序回归原理 保序回归代码(Spark Python) 保序回归原理 待续... 返回目录 保序回归代码(Spark Python) 代码里数据:https://pan.baidu.com/s/ ...
- orcal 根据打分时间计算打分情况
create or replace function F_GET_TEST(in_ny in date,in_project_id in number ) return number is sRetu ...
- sqlToolbox 1.82 Beta版 下载
下载链接:https://pan.baidu.com/s/1jCTRe0NGgEb5qF3BDN_jTQ 久违的回忆. 2019年8月30日13点43分
- 使用多块GPU进行训练 1.slim.arg_scope(对于同等类型使用相同操作) 2.tf.name_scope(定义名字的范围) 3.tf.get_variable_scope().reuse_variable(参数的复用) 4.tf.py_func(构造函数)
1. slim.arg_scope(函数, 传参) # 对于同类的函数操作,都传入相同的参数 from tensorflow.contrib import slim as slim import te ...
- 【翻译】WPF应用程序模块化开发快速入门(使用Prism+MEF)
编译并运行快速入门 需要在VisualStudio 2010上运行此快速入门示例 代码下载:ModularityWithMef.zip 先重新生成解决方案 再按F5运行此示例 说明: 在此快速入门示例 ...