题目描述

uoj 旗下有一个火车站,用来管理属于 uoj 的小火车。

火车站一共有 nn 条编号为 1,…,n1,…,n 的,只有一端的用来存放小火车的铁路,由于小火车特殊的构造,每条铁路可以停放无数辆小火车。每条铁路是相互独立的。

铁路是一个栈结构,后停放的小火车可以先出来。

每辆小火车有一个吨位 tt。

由于 NOI2016 即将到来,想要跟小火车正面作战的人多了起来,火车站管理员九条可怜每天需要处理很多事件。

事件可以概括成一下三种:

  • 1 l r 有人想跟铁路编号在 [l,r][l,r] 的每条铁路的第一辆可以开出来的小火车正面战斗,你需要统计这些小火车的吨位之和,没有火车的铁路不计入答案。
  • 2 l 编号为 ll 的铁路开走一辆火车,如果这条铁路没有小火车则不开出。
  • 3 l r x 铁路编号在 [l,r][l,r] 的每条铁路都新停放一辆吨位为 xx 的火车。

现在管理员九条可怜要去南海前线了,你需要替他管理火车站。

由于火车站很忙,所以你需要实时反馈信息,我们会用一些手段要求你强制在线,具体请看输入格式。

题解

第一个和第三个操作都是基本的线段树操作,第二个操作我们可以把它看做返回该元素的上一个版本,不难想到用主席树去维护。

我们在可持久化线段树上维护两个信息,当前节点的版本和当前区间的权值,这个版本标记我们可以把它看做lazy标记,每次访问的时候下放即可。

注意,因为是可持久化线段树,标记也要可持久化,每次下放标记时要新建节点。

代码

#include<iostream>
#include<cstdio>
#define N 500009
using namespace std;
typedef long long ll;
int tot,n,m,type,opt,l,r,T[N];
ll x,ans,val[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct segment{int rs,ls,la;ll sum;}tr[N*];
inline int newnode(int pre){int now=++tot;tr[now]=tr[pre];return now;}
inline void pushdown(int cnt,int l1,int l2){
tr[cnt].ls=newnode(tr[cnt].ls);
tr[tr[cnt].ls].la=tr[cnt].la;
tr[tr[cnt].ls].sum=1ll*val[tr[cnt].la]*l1;
tr[cnt].rs=newnode(tr[cnt].rs);
tr[tr[cnt].rs].la=tr[cnt].la;
tr[tr[cnt].rs].sum=1ll*val[tr[cnt].la]*l2;
tr[cnt].la=;
}
void upd(int &cnt,int l,int r,int L,int R,int x){
if(l>=L&&r<=R){tr[cnt].la=x;tr[cnt].sum=1ll*(r-l+)*val[x];return;}
int mid=(l+r)>>;
int tag=;
if(tr[cnt].la)pushdown(cnt,mid-l+,r-mid),tag=;
if(mid>=L){
if(!tag)tr[cnt].ls=newnode(tr[cnt].ls);
upd(tr[cnt].ls,l,mid,L,R,x);
}
if(mid<R){
if(!tag)tr[cnt].rs=newnode(tr[cnt].rs);
upd(tr[cnt].rs,mid+,r,L,R,x);
}
tr[cnt].sum=tr[tr[cnt].ls].sum+tr[tr[cnt].rs].sum;
}
int query_id(int cnt,int l,int r,int x){
if(l==r)return tr[cnt].la;
int mid=(l+r)>>;
if(tr[cnt].la)pushdown(cnt,mid-l+,r-mid);
if(mid>=x)return query_id(tr[cnt].ls,l,mid,x);
else return query_id(tr[cnt].rs,mid+,r,x);
}
ll query_sum(int cnt,int l,int r,int L,int R){
if(l>=L&&r<=R)return tr[cnt].sum;
int mid=(l+r)>>;
if(tr[cnt].la)pushdown(cnt,mid-l+,r-mid);
ll ans=;
if(mid>=L)ans+=query_sum(tr[cnt].ls,l,mid,L,R);
if(mid<R)ans+=query_sum(tr[cnt].rs,mid+,r,L,R);
return ans;
}
int main(){
n=rd();m=rd();type=rd();
for(int i=;i<=m;++i){
opt=rd();
T[i]=newnode(T[i-]);
if(opt==){
l=rd();r=rd();
l=(l+type*ans)%n+;
r=(r+type*ans)%n+;if(l>r)swap(l,r);
printf("%lld\n",ans=query_sum(T[i],,n,l,r));
}
else if(opt==){
l=rd();l=(l+type*ans)%n+;
int id=query_id(T[i],,n,l);
if(id)upd(T[i],,n,l,l,query_id(T[id-],,n,l));
}
else{
l=rd();r=rd();x=rd();
l=(l+type*ans)%n+;
r=(r+type*ans)%n+;if(l>r)l^=r^=l^=r;
val[i]=x;
upd(T[i],,n,l,r,i);
}
}
return ;
}

【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 UNR #1】火车管理

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

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

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

  6. UOJ #218. 【UNR #1】火车管理

    Description Solution 实际上添加问题就是一个线段树区间覆盖问题,打标记就好 对于弹栈操作比较难搞,实际上也就是一个历史查询,我们不需要保存栈中的每一个元素,我们通过查找历史状态就可 ...

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

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

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

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

  9. UOJ 218 火车管理

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

随机推荐

  1. IdentityServer4【Topic】之StartUp中的配置

    Startup 身份服务器是中间件和服务的组合.所有的配置都是在启动类中完成的. Configuring services 通过调用如下代码在DI(dependency inject,依赖注入)中添加 ...

  2. WPF中任务栏只显示主窗口

    我们在用WPF开发的时候,常常会遇到在主窗口打开的情况下,去显示子窗口,而此时任务栏同时显示主窗口与子窗口.这样看起来很不美观.所以在弹出子窗口之前,设置它的几个相应属性,便不会出现这种问题了. // ...

  3. 剑指offer(20)二叉搜索树与双向表

    题目: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路一:递归法 1.将左子树构造成双链表,并返回链表头节点. 2.定位至左子 ...

  4. linux不同终端的操作是如何在messages日志中区分的

    今天在定位一个问题时,查看message日志,需要知道message日志中的记录分别是哪个Xterm终端操作的.比较了半天才发现原来日志中可以通过pts来进行区分.如下所示: --12T15:::|n ...

  5. PHPStorm从入门到精通

    1. 使用phpstorm+xdebug进行调试 首先,安装php的xdebug扩展 查看phpinfo中php的版本,php的安装位数,php的是否线程安全:根据这些下载对应的xdebug.dll ...

  6. Git官方推荐用书

    用Git看了N多的Blog, 乱七八糟. 官方的推荐用书写得最好,最权威.还可以下载pdf.记录一笔. https://git-scm.com/book/zh/v2/

  7. linux 查看网段内所有IP

    如有转载,不胜荣幸.http://www.cnblogs.com/aaron-agu/ 方法一: nmap –nsP 192.168.1.0/24 #从192.168.1.0到192.168.1.25 ...

  8. LR 场景选项配置--笔记

    1 tools-options --设置关系到loadgenerator行为应用于一个场景中的所有的load generator 这些设置用于未来所有运行的场景并且通常只需要设置一次 2 expert ...

  9. 我的Git

    1.git 的安装与配置. 首先,对git进行下载.然后,在本地安装后进行版本查看,win10系统通过win+r快捷键打开控制台,然后用git --version的cmd命令查看git版本. 然后对g ...

  10. Linux环境下安装NodeJS和mongoDB

    前面的话 本文将详细介绍如何下Linux环境下安装NodeJS和mongoDB NodeJS [1]使用二进制包安装 1.在官网下载Linux环境下的NodeJS安装包 2.通过xftp软件将安装包上 ...