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 ...
随机推荐
- Java虚拟机之垃圾回收算法思想总结
1.引用计数法 这是个比较古老而经典的垃圾回收算法,其核心就是在对象被其他所引用的时候计数器加1,而当引用失去时减1.这个方法有非常严重的问题:无法此话有理循环引用的情况,还有就是每次进行加减操作比较 ...
- jQuery_复制操作
复制操作代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...
- 翻译一篇英文文章,主要是给自己看的——在ASP.NET Core Web Api中如何刷新token
原文地址 :https://www.blinkingcaret.com/2018/05/30/refresh-tokens-in-asp-net-core-web-api/ 先申明,本人英语太菜,每次 ...
- python爬取智联招聘职位信息(多进程)
测试了下,采用单进程爬取5000条数据大概需要22分钟,速度太慢了点.我们把脚本改进下,采用多进程. 首先获取所有要爬取的URL,在这里不建议使用集合,字典或列表的数据类型来保存这些URL,因为数据量 ...
- getFieldDecorator用法(一)——登录表单
之前使用antd的ui表单,却没发现这么好用的用法,推荐给大家 import React from "react"; import { Card, Form, Input, But ...
- Android_(服务)Vibrator振动器
Vibrator振动器是Android给我们提供的用于机身震动的一个服务,例如当收到推送消息的时候我们可以设置震动提醒,也可以运用到游戏当中增强玩家互动性 运行截图: 程序结构 <?xml ve ...
- SQL中模糊查询的模式匹配
SQL模糊查询的语法为: “Select column FROM table Where column LIKE 'pattern'”. SQL提供了四种匹配模式: 1. % 表示任意0个或多个字符. ...
- [论文理解] CBAM: Convolutional Block Attention Module
CBAM: Convolutional Block Attention Module 简介 本文利用attention机制,使得针对网络有了更好的特征表示,这种结构通过支路学习到通道间关系的权重和像素 ...
- 解决Oracle XE报错ORA-12516(oracle回话数超出限制)
本地安装的oracleXEUniv—oracle特别版,免费用户可以自由使用,但有连接数量和存储限制. 最近遇到一个问题,当我的SSM项目连接本地数据库oracleXE后,我的navicat再连接时就 ...
- P2672 推销员(已经补锅)
P2672 推销员 下面讲正确的贪心 题解 考虑当推销员要推销 i 家客户时,他可以有两种选择: (1)选择前 i 家疲劳值 a 最大的客户,加上这些客户里最远的距离 (2)选择前 i-1 家疲劳值 ...