建一棵答案线段树存栈顶值,两棵可持久化线段树分别存栈顶值和栈顶元素入栈时间

询问就直接在答案线段树上查,弹栈就用入栈时间在对应版本的可持久化线段树上查询即可,修改就是可持久化线段树的区间覆盖

以前一直没写过可持久化线段树的区间覆盖,这里记一下

这题只用单点查询,我们在修改时把对应的区间打上标记并将其儿子设为空,那么单点查询时答案就是访问到的最深的存在的节点

维护区间和也是可以的,直接pushdown,只不过只用对存在的儿子pushdown,在pushup时不存在的儿子的值就是当前节点的标记了

#include<stdio.h>
#include<algorithm>
using namespace std;
char c[20000010];
int ns;
#define NUM(x) ('0'<=x&&x<='9')
int rd(){
	while(!NUM(c[ns]))ns++;
	int x=0;
	while(NUM(c[ns]))x=x*10+c[ns++]-'0';
	return x;
}
int n;
struct pseg{
	struct seg{
		int l,r,v;
	}t[40000010];
	int rt[5000010],M;
	void modify(int pr,int&nr,int L,int R,int v,int l,int r){
		t[nr=++M]=t[pr];
		if(L<=l&&r<=R){
			t[nr].v=v;
			t[nr].l=t[nr].r=0;
			return;
		}
		int mid=(l+r)>>1;
		if(L<=mid)modify(t[pr].l,t[nr].l,L,R,v,l,mid);
		if(mid<R)modify(t[pr].r,t[nr].r,L,R,v,mid+1,r);
	}
	int query(int p,int l,int r,int x){
		if(x==0)return-1;
		int mid=(l+r)>>1,res;
		if(p<=mid)
			res=query(p,l,mid,t[x].l);
		else
			res=query(p,mid+1,r,t[x].r);
		return~res?res:t[x].v;
	}
	void modify(int t,int l,int r,int v){
		modify(rt[t],rt[t],l,r,v,1,n);
	}
	int query(int t,int p){
		return query(p,1,n,rt[t]);
	}
}top,in;
int s[2000010],t[2000010];
void gao(int x,int len,int v){
	t[x]=v;
	s[x]=len*v;
}
void pushdown(int x,int ln,int rn){
	if(t[x]){
		gao(x<<1,ln,t[x]);
		gao(x<<1|1,rn,t[x]);
		t[x]=0;
	}
}
void pushup(int x){s[x]=s[x<<1]+s[x<<1|1];}
void modify(int L,int R,int v,int l,int r,int x){
	if(L<=l&&r<=R)return gao(x,r-l+1,v);
	int mid=(l+r)>>1;
	pushdown(x,mid-l+1,r-mid);
	if(L<=mid)modify(L,R,v,l,mid,x<<1);
	if(mid<R)modify(L,R,v,mid+1,r,x<<1|1);
	pushup(x);
}
int query(int L,int R,int l,int r,int x){
	if(L<=l&&r<=R)return s[x];
	int mid=(l+r)>>1,s=0;
	pushdown(x,mid-l+1,r-mid);
	if(L<=mid)s+=query(L,R,l,mid,x<<1);
	if(mid<R)s+=query(L,R,mid+1,r,x<<1|1);
	return s;
}
int main(){
	fread(c,1,20000010,stdin);
	in.t[0].v=-1;
	top.t[0].v=-1;
	int m,on,las,op,i,l,r,x,v;
	n=rd();
	m=rd();
	on=rd();
	las=0;
	for(i=1;i<=m;i++){
		top.rt[i]=top.rt[i-1];
		in.rt[i]=in.rt[i-1];
		op=rd();
		if(op==1){
			l=(rd()+on*las)%n+1;
			r=(rd()+on*las)%n+1;
			if(l>r)swap(l,r);
			las=query(l,r,1,n,1);
			printf("%d\n",las);
		}
		if(op==2){
			l=(rd()+on*las)%n+1;
			x=in.query(i,l);
			if(x>0){
				v=in.query(x-1,l);
				if(v==-1)v=0;
				in.modify(i,l,l,v);
				v=top.query(x-1,l);
				if(v==-1)v=0;
				modify(l,l,v,1,n,1);
				top.modify(i,l,l,v);
			}
		}
		if(op==3){
			l=(rd()+on*las)%n+1;
			r=(rd()+on*las)%n+1;
			x=rd();
			if(l>r)swap(l,r);
			modify(l,r,x,1,n,1);
			top.modify(i,l,r,x);
			in.modify(i,l,r,i);
		}
	}
}

[UOJ218]火车管理的更多相关文章

  1. 「UOJ218」火车管理

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

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

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

  3. 【UNR #1】火车管理

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

  4. UOJ 218 火车管理

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

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

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

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

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

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

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

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

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

  9. UNR #1 火车管理

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

随机推荐

  1. It is possible that this issue is resolved by uninstalling an existi

    使用真机连接Android Studio测试时出现这样的错误: 解决方法: 设置Android Studio 中Instant Run中的选项为不选中 根据以下路径,找到Instant Run中的选项 ...

  2. 土司论坛nc反弹神器使用方法

    说明: PS:我本机是linux,因为没有服务器所以使用win7来演示.倘若你是windows可以在本机生成dll以后再放到服务器上面去执行dll即可反弹shell物理机ip:192.168.1.12 ...

  3. peewee在flask中的配置

    # 原文:https://blog.csdn.net/mouday/article/details/85332510 Flask的钩子函数与peewee.InterfaceError: (0, '') ...

  4. 深入分析_linux_spinlock_实现机制【转】

    转自:http://blog.csdn.net/electrombile/article/details/51289813 在 x86 平台上,spinlock 主要通过处理器的 lock 指令前缀实 ...

  5. iOS WKWebView ios9以上版本配置 与 设置UserAgent(用户代理), 解决点击web, 客户端接收不到web事件问题

    项目运行在ios9上需要在info.plist文件中配置加入如下信息, App Transport Security Settings Allow Arbitrary Loads = YES < ...

  6. VPS性能测试(2):内存大小、交换空间、高速缓存、实际使用内存

    1.要想查看购买的VPS主机的内存信息,执行:cat /proc/meminfo,主要是看内存大小.交换空间.高速缓存 2.VPS主机实际使用内存大小.Linux管理内存的机制是这样的:无论物理内存有 ...

  7. ServerSocket和Socket通信

    服务器端: 1.服务器端建立通信ServerSocket对象,并设置端口号 2.服务器建立Socket接收客户端连接 3.建立IO输入流读取客户端发送的数据 4.建立IO输出流向客户端输出数据 客户端 ...

  8. python--tesseract

    tesseract的介绍 我们爬虫会受到阻碍,其中一个便是我们在模拟登陆或者请求一些数据的时候,出现的图形验证码,因此我们需要一种能叫图形验证码识别成文本的技术.将图片翻译成文字一般称为光学文字识别( ...

  9. 如何测试一台主机的IP和端口是否能连通,ping telnet

    通过ping 判断一台主机是否开机. 通过:telnet 121.199.167.99 61616  判断一台主机的端口是否能连通. 本机------本地防火墙-------本地路由器-------- ...

  10. Exchanger学习

    Java并发新构件之Exchanger JDK API Exchaner 介绍 JDK API 解释 A synchronization point at which threads can pair ...