UOJ#218. 【UNR #1】火车管理 线段树 主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ218.html
题解
如果我们可以知道每次弹出栈之后新的栈顶是什么,那么我们就可以在一棵区间覆盖、区间求和的线段树上完成这个问题。
于是本题的重点转到了如何求新的栈顶。
考虑用一个主席树维护一下每一个时刻每一个位置的栈顶元素的进栈时间,那么新的栈顶就是 当前位置栈顶的进栈时间-1 这时候的栈顶元素,然后这个东西也可以用我们维护的进栈时间来得到,所以我们只需要弄一个支持区间覆盖单点查询历史版本的主席树;这里区间覆盖有一个小技巧:假设节点 x 所代表的区间都被覆盖了,那么修改完 val[x] 之后令 ls[x] = rs[x] = x 即可。
代码
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=500005;
int n,m,k;
int lastans=0;
int hisv[N];
namespace seg{
const int S=N<<2;
int sum[S],add[S],len[S];
void build(int rt,int L,int R){
len[rt]=R-L+1,sum[rt]=add[rt]=0;
if (L==R)
return;
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
build(ls,L,mid);
build(rs,mid+1,R);
}
void pushdown(int rt){
int ls=rt<<1,rs=ls|1;
if (add[rt]){
add[ls]=add[rs]=add[rt];
sum[ls]=add[rt]*len[ls];
sum[rs]=add[rt]*len[rs];
add[rt]=0;
}
}
void update(int rt,int L,int R,int xL,int xR,int v){
if (R<xL||L>xR)
return;
if (xL<=L&&R<=xR){
sum[rt]=v*len[rt];
add[rt]=v;
return;
}
pushdown(rt);
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
update(ls,L,mid,xL,xR,v);
update(rs,mid+1,R,xL,xR,v);
sum[rt]=sum[ls]+sum[rs];
}
int Query(int rt,int L,int R,int xL,int xR){
if (R<xL||L>xR)
return 0;
if (xL<=L&&R<=xR)
return sum[rt];
pushdown(rt);
int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
return Query(ls,L,mid,xL,xR)+Query(rs,mid+1,R,xL,xR);
}
}
namespace pt{
const int S=N*100;
int val[S],ls[S],rs[S],root[N],cnt;
void init(){
root[0]=cnt=ls[1]=rs[1]=1;
val[1]=0;
}
void update(int prt,int &rt,int L,int R,int xL,int xR,int v){
if (R<xL||L>xR)
return;
if (rt==prt)
rt=++cnt,val[rt]=val[prt],ls[rt]=ls[prt],rs[rt]=rs[prt];
if (xL<=L&&R<=xR){
val[rt]=v;
ls[rt]=rs[rt]=rt;
return;
}
int mid=(L+R)>>1;
update(ls[prt],ls[rt],L,mid,xL,xR,v);
update(rs[prt],rs[rt],mid+1,R,xL,xR,v);
}
int Query(int rt,int L,int R,int x){
if (L==R)
return val[rt];
int mid=(L+R)>>1;
if (x<=mid)
return Query(ls[rt],L,mid,x);
else
return Query(rs[rt],mid+1,R,x);
}
}
using pt::root;
int main(){
n=read(),m=read(),k=read();
seg::build(1,1,n);
pt::init();
hisv[0]=0;
for (int T=1;T<=m;T++){
root[T]=root[T-1];
int type=read(),L=(read()+lastans*k)%n+1,R,x;
if (type==1){
R=(read()+lastans*k)%n+1;
if (L>R)
swap(L,R);
printf("%d\n",lastans=seg::Query(1,1,n,L,R));
}
else if (type==2){
int t1=pt::Query(root[T-1],1,n,L);
t1=pt::Query(root[max(t1-1,0)],1,n,L);
seg::update(1,1,n,L,L,hisv[t1]);
pt::update(root[T-1],root[T],1,n,L,L,t1);
}
else if (type==3){
R=(read()+lastans*k)%n+1,x=read();
if (L>R)
swap(L,R);
hisv[T]=x;
seg::update(1,1,n,L,R,x);
pt::update(root[T-1],root[T],1,n,L,R,T);
}
}
return 0;
}
UOJ#218. 【UNR #1】火车管理 线段树 主席树的更多相关文章
- 线段树简单入门 (含普通线段树, zkw线段树, 主席树)
线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)
先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...
- Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)
Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...
- 小结:线段树 & 主席树 & 树状数组
概要: 就是用来维护区间信息,然后各种秀智商游戏. 技巧及注意: 一定要注意标记的下放的顺序及影响!考虑是否有叠加或相互影响的可能! 和平衡树相同,在操作每一个节点时,必须保证祖先的tag已经完全下放 ...
- BZOJ5011 [JXOI2017]颜色 【线段树 + 主席树】
题目链接 BZOJ5011 题解 一定只有我这种智障会用这么奇怪的方法做这道题.. 由题我们知道最后剩余的一定是一个区间,而且区间内的颜色不存在于区间外 所以我们的目的就是为了找到这样的区间的数量 区 ...
- 洛谷P3834 可持久化线段树(主席树)模板
题目:https://www.luogu.org/problemnew/show/P3834 无法忍受了,我要写主席树! 解决区间第 k 大查询问题,可以用主席树,像前缀和一样建立 n 棵前缀区间的权 ...
- [学习笔记] 可持久化线段树&主席树
众所周知,线段树是一个非常好用也好写的数据结构, 因此,我们今天的前置技能:线段树. 然而,可持久化到底是什么东西? 别急,我们一步一步来... step 1 首先,一道简化的模型: 给定一个长度为\ ...
随机推荐
- Drag(拖拽)和Move(移动)两个脚本
Drag using System.Collections; using System.Collections.Generic; using UnityEngine; public class Dra ...
- 【WC2018】即时战略
题目描述 小M在玩一个即时战略(Real Time Strategy)游戏.不同于大多数同类游戏,这个游戏的地图是树形的. 也就是说,地图可以用一个由 n个结点,n?1条边构成的连通图来表示.这些结点 ...
- 解决Parameter '__frch_item_0' not found. Available parameters 问题
1. 问题描述: 出现如下问题,执行报错信息 Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org ...
- postgreSQL学习(二):pgsql的一些基础操作
在上一篇文章中我们学习了怎么安装pgsql,安装好了后,我们来学习一下怎么对pgsql进行创建操作以及相关的crud的操作啦 一 创建数据库 $ createdb test 然后你可能会遇到如下的错误 ...
- maven 构建参数和命令
mvn常用参数 mvn -e 显示详细错误 mvn -U 强制更新snapshot类型的插件或依赖库(否则maven一天只会更新一次snapshot依赖) mvn -o 运行offline模式,不联网 ...
- 金融量化分析【day111】:Matplotib-绘制K线图
一.绘制k线图 1.使用金融包出错解决 1.错误代码 ImportError: No module named finance 2.解决办法 https://github.com/matplotlib ...
- Docker下安装Jenkins
Docker安装参见:https://www.cnblogs.com/hackyo/p/9280042.html 安装Jenkins: docker run \ -u root \ --rm \ -d ...
- docker学习-----docker服务的安装
docker 以下观点个人理解,只做参考 一.docker本身的优势 1.docker他本身是一个容器,用来方便我们项目打包,做服务器虚拟化,统一开发者环境等多种优势:运行于docker上的项目可以快 ...
- Trie树的二三事QWQ
写在前面 Trie,又称字典树,是一种用于实现字符串快速检索的多叉树结构.Trie的每个结点都拥有若干字符指针,若在插入或检索字符串时扫描到一个字符c,就沿着当前节点的c这个字符指针,走向该指针指向的 ...
- Linux Shell远程执行命令
1.问题描述 经常需要远程到其他节点上执行一些shell命令,如果分别ssh到每台主机上再去执行很麻烦,下边介绍shell命令远程执行的方法. 前提: 远程电脑之间已经配置ssh免密码登陆 2.脚本方 ...