原文链接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】火车管理 线段树 主席树的更多相关文章

  1. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  2. 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))

    函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...

  3. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

  4. Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)

    先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...

  5. Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)

    Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...

  6. 小结:线段树 & 主席树 & 树状数组

    概要: 就是用来维护区间信息,然后各种秀智商游戏. 技巧及注意: 一定要注意标记的下放的顺序及影响!考虑是否有叠加或相互影响的可能! 和平衡树相同,在操作每一个节点时,必须保证祖先的tag已经完全下放 ...

  7. BZOJ5011 [JXOI2017]颜色 【线段树 + 主席树】

    题目链接 BZOJ5011 题解 一定只有我这种智障会用这么奇怪的方法做这道题.. 由题我们知道最后剩余的一定是一个区间,而且区间内的颜色不存在于区间外 所以我们的目的就是为了找到这样的区间的数量 区 ...

  8. 洛谷P3834 可持久化线段树(主席树)模板

    题目:https://www.luogu.org/problemnew/show/P3834 无法忍受了,我要写主席树! 解决区间第 k 大查询问题,可以用主席树,像前缀和一样建立 n 棵前缀区间的权 ...

  9. [学习笔记] 可持久化线段树&主席树

    众所周知,线段树是一个非常好用也好写的数据结构, 因此,我们今天的前置技能:线段树. 然而,可持久化到底是什么东西? 别急,我们一步一步来... step 1 首先,一道简化的模型: 给定一个长度为\ ...

随机推荐

  1. 用django2.1开发公司官网(上)

    1.在MySQL中新建数据库 show databases;//查看已经有的数据库 create database guanwang; 2.新建django项目guan 1.使用pycharm新建dj ...

  2. Python终极coding

    作为一名程序员,除了需要具备解决问题的思路以外,代码的质量和简洁性也很关键.因为从一个人的代码可以直接看出你的基本功.对于Python而言,这就意味着你需要对Python的内置功能和库有很深入的了解. ...

  3. zabbix Server 4.0 部署及之内置item使用案例

    zabbix Server 4.0 部署及之内置item使用案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.zabbix组件架构概述(图片摘自网络) 1>.zabbi ...

  4. va注解应用实例 - Annotation, 自定义注解, 注解类规则【转】

    本文介绍了java的自定义注解及注解类编写的规则, 并通过实例来说明下如何使用java的注解. 实例演示了注解在类,构造方法,方法和字段的使用. 可以从这里下载到完成的工程代码: http://dl. ...

  5. 基于alpine制作php镜像

    alpine包搜索https://pkgs.alpinelinux.org/ 安装依赖库 apk add --no-cache xxx 可以基于php apline镜像自行增加或删除扩展. https ...

  6. ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树+LCA)

    https://nanti.jisuanke.com/t/31462 题意 一个N*M的矩形,每个格点到其邻近点的边有其权值,需要构建出一个迷宫,使得构建迷宫的边权之和最小,之后Q次查询,每次给出两点 ...

  7. [物理学与PDEs]第1章习题13 静磁场的矢势在媒质交界面上的条件

    试讨论对静磁场的矢势, 如何决定其在媒质交界面上的条件. 解答: 由 $\rot{\bf A}={\bf B}$ 知 $$\bex \oint_l {\bf A}\cdot\rd {\bf l} =\ ...

  8. /etc/profile文件被改坏导致命令不可用

    这几天在装一个软件,设置环境变量的时候,不小心把/etc/profile文件改坏了(就是没配置对),在source /etc/profile后导致所有命令都不可用了.出现如下报错: -bash: xx ...

  9. .net使用Aspose.Words进行Word替换操作的实现代码

    DLL文件下载 示例: Aspose.Words.Document doc = new Aspose.Words.Document(TempFile); Aspose.Words.DocumentBu ...

  10. FM(Factorization Machines)

    摘自 https://www.jianshu.com/p/1687f8964a32 https://blog.csdn.net/google19890102/article/details/45532 ...