Description

Solution

实际上添加问题就是一个线段树区间覆盖问题,打标记就好

对于弹栈操作比较难搞,实际上也就是一个历史查询,我们不需要保存栈中的每一个元素,我们通过查找历史状态就可以了

这样用主席树维护复杂度是 \(O(n*logn)\) 的

具体是这样的:

假设我们要弹出位置 \(x\) 的栈顶元素,那么在线段树中维护一个值 \(t\),表示最近的一次修改是 \(t\) 时刻

那么上上次修改就可以通过查询 \(t-1\) 时刻的 \(t\) 找出,相当于保存了一个前驱

用主席树维护这个时间就好了

注意内存有些卡,有一些技巧:

1.首先对于查询的线段树是全局的,不需要动态开点

2.对于线段树中的一个节点 \(x\) ,如果它的左右儿子都没有儿子,那么下一次做区间覆盖时,就不需要对 \(x\) 新建两个节点

#include<bits/stdc++.h>
#define lo (o<<1)
#define ro (o<<1|1)
using namespace std;
const int N=5e5+10;
int n,m,ty,rt[N],a[N],tt=0;
struct data{
int ls,rs,lag;
data(){lag=-1;}
}tr[N*130];
int T[N*4],la[N*4],in[N*130];
inline void pushdown(int o){
if(tr[o].lag==-1)return ;
int t=tr[o].lag;tr[o].lag=-1;
if(!in[o] || in[tr[o].ls] || in[tr[o].rs]){
tr[++tt]=tr[tr[o].ls];tr[o].ls=tt;
tr[++tt]=tr[tr[o].rs];tr[o].rs=tt;in[o]=1;
}
int ls=tr[o].ls,rs=tr[o].rs;
tr[ls].lag=t;tr[rs].lag=t;
}
inline void Push(int o,int l,int r){
if(la[o]==-1)return ;
int k=la[o],mid=(l+r)>>1;la[o]=-1;
T[lo]=k*(mid-l+1);la[lo]=k;
T[ro]=k*(r-mid);la[ro]=k;
}
inline void upd(int o){T[o]=T[lo]+T[ro];}
inline int qry(int o,int l,int r,int sa,int se){
if(sa<=l && r<=se)return T[o];
int mid=(l+r)>>1,ret=0;
Push(o,l,r);
if(se<=mid)ret=qry(lo,l,mid,sa,se);
else if(sa>mid)ret=qry(ro,mid+1,r,sa,se);
else ret=qry(lo,l,mid,sa,mid)+qry(ro,mid+1,r,mid+1,se);
upd(o);
return ret;
}
inline int qt(int x,int l,int r,int sa){
if(l==r)return tr[x].lag;
int mid=(l+r)>>1,ret=0;
pushdown(x);in[x]=1;
if(sa<=mid)ret=qt(tr[x].ls,l,mid,sa);
else ret=qt(tr[x].rs,mid+1,r,sa);
return ret;
}
inline void add(int o,int l,int r,int sa,int se,int t){
if(sa<=l && r<=se){T[o]=(r-l+1)*t;la[o]=t;return ;}
Push(o,l,r);
int mid=(l+r)>>1;
if(se<=mid)add(lo,l,mid,sa,se,t);
else if(sa>mid)add(ro,mid+1,r,sa,se,t);
else add(lo,l,mid,sa,mid,t),add(ro,mid+1,r,mid+1,se,t);
upd(o);
}
inline void addtag(int &x,int l,int r,int sa,int se,int t){
tr[++tt]=tr[x];x=tt;
if(sa<=l && r<=se){tr[x].lag=t;return ;}
pushdown(x);
int mid=(l+r)>>1;in[x]=1;
if(se<=mid)addtag(tr[x].ls,l,mid,sa,se,t);
else if(sa>mid)addtag(tr[x].rs,mid+1,r,sa,se,t);
else addtag(tr[x].ls,l,mid,sa,mid,t),addtag(tr[x].rs,mid+1,r,mid+1,se,t);
}
int main(){
freopen("railway.in","r",stdin);
freopen("railway.out","w",stdout);
cin>>n>>m>>ty;
int op,l,r,ans=0,x,y;
memset(la,-1,sizeof(la));
for(int i=1;i<=m;i++){
rt[i]=rt[i-1];
scanf("%d%d",&op,&l);
l=(l+ans*ty)%n+1;
if(op==1){
scanf("%d",&r);
r=(r+ans*ty)%n+1;
if(l>r)swap(l,r);
printf("%d\n",ans=qry(1,1,n,l,r));
}
else if(op==2){
x=qt(rt[i],1,n,l);
if(x){
y=qt(rt[x-1],1,n,l);
addtag(rt[i],1,n,l,l,y);add(1,1,n,l,l,a[y]);
}
}
else if(op==3){
scanf("%d%d",&r,&a[i]);
r=(r+ans*ty)%n+1;
if(l>r)swap(l,r);
add(1,1,n,l,r,a[i]);
addtag(rt[i],1,n,l,r,i);
}
}
return 0;
}

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

  1. UNR #1 火车管理

    很简单 用一个线段树维护 1.答案 2.当前栈顶是什么时候push进来的 然后用一棵以时间为版本的可持久化线段树维护每个操作之后第一个覆盖到他的操作是哪个 就可以了 询问直接在线段树上询问,修改在两棵 ...

  2. 【UNR #1】火车管理(主席树)

    [UNR #1]火车管理(主席树) 好好的代码被 \(extra\ test\) 卡常了...我就放一个目前最快的版本吧... 题意简化: 有 \(n\) 个栈,\(m\) 次操作. 将 \(x\) ...

  3. 「UOJ218」火车管理

    「UOJ218」火车管理 解题思路:观察发现,在弹出 \(x\) 之前,它前面这个元素都是保持不变的,所以可以用一棵可持久化线段树维护每一个栈顶元素的插入时间,每次找到当前时间\(-1\) 的版本就可 ...

  4. [UOJ#128][BZOJ4196][Noi2015]软件包管理器

    [UOJ#128][BZOJ4196][Noi2015]软件包管理器 试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管 ...

  5. UOJ#218. 【UNR #1】火车管理 线段树 主席树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html 题解 如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖.区间求和 ...

  6. Uoj #218. 【UNR #1】火车管理 可持久化线段树+思维

    Code: #include<bits/stdc++.h> #define maxn 500005 using namespace std; int n,Q,ty,lastans=0; i ...

  7. UOJ 218 火车管理

    http://uoj.ac/problem/218 思路:建立一个可持久化线段树,代表这个位置的火车是哪辆,然后再弄一个线段树维护答案. 如果询问,直接询问线段树. 如果区间压入,直接在主席树上面压入 ...

  8. 【UOJ UNR #1】火车管理

    来自FallDream的博客,未经允许,请勿转载,谢谢. 题面 考虑用可持久化线段树直接维护每个点在不同时刻,第一辆车的编号. 这样3操作就变成了区间赋值,1操作变成区间和 2操作的话,只需要查询一下 ...

  9. 【UOJ UNR #1】火车管理 可持久化线段树

    用可持久化线段树维护每个站的第一辆车和每个站的前一次更新的位置即可. #include<iostream> #include<cstring> #include<cstd ...

随机推荐

  1. Struts2学习第4天--拦截器

    第1章     Struts2_day04笔记 1.1      上次课内容回顾 l  OGNL表达式 n  OGNL的概述 u  OGNL:对象图导航语言,是一门功能强大的表达式语言. n  OGN ...

  2. Python的__getattribute__二三事

    本来以为自己对__getattribute__已经比较了解了,结果用到的时候,才发现有一些知识点之前一直没有真正弄明白,记录如下(针对python3,python2差异较大): object类有__g ...

  3. Leetcode 856. Score of Parentheses 括号得分(栈)

    Leetcode 856. Score of Parentheses 括号得分(栈) 题目描述 字符串S包含平衡的括号(即左右必定匹配),使用下面的规则计算得分 () 得1分 AB 得A+B的分,比如 ...

  4. [web]Servlet中的Listener和Filter

    建议先看看 ——> Servlet工作原理 一.Listener 在Tomcat服务中,Listener的设计是基于观察者模式的,目前在Servlet中提供6中两类事件的观察者接口,它们分别是: ...

  5. HTML-CSS样式表-★★★常用属性★★★及基本概念、分类、选择器

    样式属性 背景与前景: background-color:#F90; /*背景颜色,样式表优先级最高*/ background-image:url(路径); /*设置背景图片(默认)*/ backgr ...

  6. 数据库--sql文件

    sql 脚本是包含一到多个 sql 命令的 sql 语句集合 使用 Linux: mysqldump 命令 1.导出数据和表结构: mysqldump -u 用户名 -p 数据库名称 > nam ...

  7. anaconda安装出现failed to create anacoda menue

    1.卸载Anaconda后重新安装Anaconda出现各种问题,粗暴解决方式:直接将安装目录放在C盘主路径下,完美解决. 2.然后无选择忽略,忽略,忽略,提示安装成功,依旧没有 菜单 进入 cmd,找 ...

  8. 【Alpha】Scrum Meeting 0&1

    前言 第0次会议和第1次会议分别在4月1日和4月2日21:00由PM在大运村一公寓3层召开. 第0次时长50min,主要明确了接下来的任务,对工作进行了分配. 第1次会议时长20min,调研了当日工作 ...

  9. [转] Jenkins pipeline 踩坑集合

    [From] https://testerhome.com/topics/10328 前言 最近由于项目需要,接触到了Jenkins 2.0版本,其中最重要的特性就是提供了对pipeline的支持.简 ...

  10. yum的repo文件详解、以及epel简介、yum源的更换

    一.什么是repo文件        repo文件是Fedora中yum源(软件仓库)的配置文件,通常一个repo文件定义了一个或者多个软件仓库的细节内容,例如我们将从哪里下载需要安装或者升级的软件包 ...