题意

\(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_火车管理的更多相关文章

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

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

  2. 「UOJ218」火车管理

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

  3. 【UNR #1】火车管理

    题目描述 uoj 旗下有一个火车站,用来管理属于 uoj 的小火车. 火车站一共有 nn 条编号为 1,…,n1,…,n 的,只有一端的用来存放小火车的铁路,由于小火车特殊的构造,每条铁路可以停放无数 ...

  4. UOJ 218 火车管理

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

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

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

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

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

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

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

  8. [UOJ218]火车管理

    建一棵答案线段树存栈顶值,两棵可持久化线段树分别存栈顶值和栈顶元素入栈时间 询问就直接在答案线段树上查,弹栈就用入栈时间在对应版本的可持久化线段树上查询即可,修改就是可持久化线段树的区间覆盖 以前一直 ...

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

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

随机推荐

  1. jQuery_页面加载问题

    运行如下代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...

  2. ABP core2.2错误笔记,持续更新

    注:以下问题全部基于版本 © 2019 MLCDZ. Version 4.3.0.0 [20190830]  .net core 的版本为2.2 1.System.InvalidOperationEx ...

  3. 51nod11443-路径和树(图论,最短路,最小生成树)

    1443 路径和树 题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 给定一幅无向带权连通图G = (V, E) ...

  4. 在mac中,npm安装或者卸载失败,提示没有权限

    在终端输入 sudo chown -R $USER /usr/local 输入开机密码

  5. CentOS 7,使用yum安装Nginx

    https://www.centos.bz/2018/01/centos-7%EF%BC%8C%E4%BD%BF%E7%94%A8yum%E5%AE%89%E8%A3%85nginx/ 文章目录 [隐 ...

  6. 一、MongoDB为用户设置访问权限

    MongoDB默认设置为无权限访问限制 注:基于Windows平台 MongoDB在本机安装部署好后 1. 输入命令:show dbs,你会发现它内置有两个数据库,一个名为admin,一个名为loca ...

  7. SQL 表 数据备份

    insert into SMTTemporarySave select * from [MSV0CIMDB].[PICS_20170706].dbo.SMTTemporarySave

  8. mesh之孔洞检测

    mesh之孔洞检测 图1 检测孔洞点 图2 检测孔洞点 图3 检测孔洞点 图4 细节

  9. Cas服务器以及客户端搭建

    一.搭建cas服务器 官网:http://jasig.github.io/cas/ Cas Server 下载:http://developer.jasig.org/cas/ Cas Client 下 ...

  10. 4. 获取当前的文件夹的路径,以及当前文件名的路径 os.path.realpath

    使用os.path.realpath(__file__) 获得当前的文件夹的路径名, 使用os.path.split 进行路径切割 import os src, _= os.path.split(os ...