原文链接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. mybatis返回结果封装为map的探索

    需求 根据课程id 列表,查询每个课程id的总数,放到一个map里 最简单的就是循环遍历,每一个都查询一次网上说mybatis可以返回Map 和 List<Map>两种类型 尝试 直接返回 ...

  2. BZOJ4671异或图

    题目描述 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中, 否则这条边不在 ...

  3. Prometheus监控elasticsearch集群(以elasticsearch-6.4.2版本为例)

    部署elasticsearch集群,配置文件可"浓缩"为以下: cluster.name: es_cluster node.name: node1 path.data: /app/ ...

  4. sublime text 批量删除空白行

    CTRL+H打开replace功能,勾选上左侧的regular expression,并填写 find what栏 : \s+$  (正则表达式)replace with栏 : (这行留空) 接着点r ...

  5. MQ在高并发环境下,如果队列满了,如何防止消息丢失?

    1.为什么MQ能解决高并发环境下的消息堆积问题? MQ消息如果堆积,消费者不会立马消费所有的消息,不具有实时性,所以可以解决高并发的问题. 性能比较好的消息中间件:Kafka.RabbitMQ,Roc ...

  6. Vue(小案例_vue+axios仿手机app)_上拉加载

    ---恢复内容开始--- 一.前言                                                                                    ...

  7. BZOJ3932 主席树

    https://www.lydsy.com/JudgeOnline/problem.php?id=3932 题意:给出一些带有等级的线段,求一点上前K小个等级线段的等级之和 询问是对于每一个点询问前K ...

  8. bootstrap浅谈

    学习地址:http://www.runoob.com/bootstrap/bootstrap-tutorial.html 自己练习了下 主要是使用了bootstrap中包含的class类样式,只要给相 ...

  9. (转)如何阅读OpenStack源码

    1 关于该项目 本项目使用在线绘图工具web sequencediagrams完成,目标是图形化OpenStack的所有操作流程,通过操作序列图能快速学习Openstack的工作原理,理清各个组件的关 ...

  10. CMDB服务器管理系统【s5day92】:服务器管理回顾

    一.服务器管理回顾 1.requests 发送: requests.post(url='',data=,json=) requests.get() Django接受: request.POST, co ...