平衡树分裂钛好玩辣!

题目描述

方伯伯正在做他的 OJ。现在他在处理 OJ 上的用户排名问题。

OJ 上注册了 \(n\) 个用户,编号为 \(1\sim n\),一开始他们按照编号排名。方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号:

  1. 操作格式为 1 x y,意味着将编号为 \(x\) 的用户编号改为 \(y\),而排名不变,执行完该操作后需要输出该用户在排名中的位置,数据保证 \(x\) 必然出现在排名中,同时 \(y\) 是一个当前不在排名中的编号。
  2. 操作格式为 2 x,意味着将编号为 \(x\) 的用户的排名提升到第一位,执行完该操作后需要输出执行该操作前编号为 \(x\) 用户的排名。
  3. 操作格式为 3 x,意味着将编号为 \(x\) 的用户的排名降到最后一位,执行完该操作后需要输出执行该操作前编号为 \(x\) 用户的排名。
  4. 操作格式为 4 k,意味着查询当前排名为 \(k\) 的用户编号,执行完该操作后需要输出当前操作用户的编号。 但同时为了防止别人监听自己的工作,方伯伯对他的操作进行了加密,即将四种操作的格式分别改为了:
1 x+a y+a
2 x+a
3 x+a
4 k+a

其中 \(a\) 为上一次操作得到的输出,一开始 \(a=0\)。

例如: 上一次操作得到的输出是 5

这一次操作的输入为:1 13 15

因为这个输入是经过加密后的,所以你应该处理的操作是1 8 10

现在你截获了方伯伯的所有操作,希望你能给出结果。

输入输出格式

输入格式:

输入的第一行包含两个用空格分隔的整数 \(n\) 和 \(m\),表示初始用户数和操作数。

此后有 \(m\) 行,每行是一个询问,询问格式如上所示。

输出格式:

输出包含 \(m\) 行。每行包含一个整数,其中第 \(i\) 行的整数表示第 \(i\) 个操作的输出。

输入输出样例

输入样例:

10 10
1 2 11
3 13
2 5
3 7
2 8
2 10
2 11
3 14
2 18
4 9

输出样例:

2
2
2
4
3
5
5
7
8
11

数据范围与说明

对于 \(100\%\) 的数据,\(1\le n\le 10^8,\ 1\le m\le 10^5\)。

输入保证对于所有的操作,\(x\) 必然已经出现在队列中,同时对于所有操作 1,\(1\le y\le 2\times 10^8\),并且 \(y\) 没有出现在队列中。

对于所有操作 4,保证 \(1\le k\le n\)。

题解:

平衡树”区间移动“题。

用带点分裂的 fhq Treap 移动区间,用线段树维护区间内元素在平衡树上的数组下标。

在平衡树上保留父亲信息。其中fa[root]=0 ,然后就可以顺着爬上去来计算每个节点的排名。

时间复杂度 \(O(m\log n)\)。

Code:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#define len(x) (r[x]-l[x]+1)
#define mid ((L+R)>>1)
#define N 200000000 namespace sgt
{
int ls[6000000],rs[6000000],v[6000000],lazy[6000000],pcnt=1;
void pushdown(int k,int L,int R)
{
if(!lazy[k]||L==R)
return;
int x=lazy[k];
v[ls[k]]=x;
lazy[ls[k]]=x;
v[rs[k]]=x;
lazy[rs[k]]=x;
lazy[k]=0;
return;
}
void change(int k,int l,int r,int L,int R,int x)//把区间[l,r]改成x
{
if(l<=L&&r>=R)
{
v[k]=x;
lazy[k]=x;
return;
}
if(r<L||l>R)
return;
if(!ls[k])
ls[k]=++pcnt;
if(!rs[k])
rs[k]=++pcnt;
pushdown(k,L,R);
change(ls[k],l,r,L,mid,x);
change(rs[k],l,r,mid+1,R,x);
}
int ask(int k,int p,int L,int R)//求点i的编号
{
if(!ls[k]&&!rs[k])
return v[k];
pushdown(k,L,R);
if(p<=mid)
return ask(ls[k],p,L,mid);
return ask(rs[k],p,mid+1,R);
}
}
int root=0; namespace bst
{
int rdm[200100],ls[200100],rs[200100],fa[200100];
int sz[200100],l[200100],r[200100];
int pcnt=0;
int Newnode(int L,int R)
{
++pcnt;
l[pcnt]=L;
r[pcnt]=R;
sz[pcnt]=R-L+1;
rdm[pcnt]=rand();
sgt::change(1,L,R,1,N,pcnt);
return pcnt;
}
void maintain(int k)
{
sz[k]=sz[ls[k]]+sz[rs[k]]+r[k]-l[k]+1;
fa[ls[k]]=k;
fa[rs[k]]=k;
}
int Merge(int a,int b)
{
if(!a||!b)
return a|b;
if(rdm[a]<rdm[b])
{
rs[a]=Merge(rs[a],b);
maintain(a);
return a;
}
ls[b]=Merge(a,ls[b]);
maintain(b);
return b;
}
void split(int rt,int x,int &a,int &b)
{
if(!rt)
{
a=0,b=0;
return;
}
int L=sz[ls[rt]],R=r[rt]-l[rt]+1;
if(x<=L)
{
b=rt;
split(ls[rt],x,a,ls[b]);
}
else if(x<L+R)
{
x-=L;
a=rt;
b=Newnode(l[rt]+x,r[rt]);
r[a]=l[rt]+x-1; rs[b]=rs[a];
rs[a]=0;
maintain(a);
maintain(b);
return;
}
else
{
a=rt;
split(rs[rt],x-L-R,rs[a],b);
}
maintain(rt);
}
int Rank(int p)
{
int k=sgt::ask(1,p,1,N); int ans=sz[ls[k]]+p-l[k]+1; while(fa[k])
{
if(k==rs[fa[k]])
ans+=sz[ls[fa[k]]]+len(fa[k]);
k=fa[k];
}
return ans;
}
} int main()
{
int n,m,op,x,y,z=0;
int a,b,c;
scanf("%d%d",&n,&m);
root=bst::Newnode(1,n);
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
x-=z,y-=z;
z=bst::Rank(x); printf("%d\n",z); bst::split(root,z-1,a,b);
bst::split(b,1,b,c); bst::l[b]=bst::r[b]=y;
sgt::change(1,y,y,1,N,b); root=bst::Merge(bst::Merge(a,b),c);
bst::fa[root]=0;
}
else if(op==2||op==3)
{
scanf("%d",&x);
x-=z;
z=bst::Rank(x); printf("%d\n",z); bst::split(root,z-1,a,b);
bst::split(b,1,b,c); if(op==2)
root=bst::Merge(bst::Merge(b,a),c);
else
root=bst::Merge(bst::Merge(a,c),b);
bst::fa[root]=0;
}
else
{
scanf("%d",&x);
x-=z;
bst::split(root,x-1,a,b);
bst::split(b,1,b,c);
z=bst::l[b];
printf("%d\n",z);
root=bst::Merge(bst::Merge(a,b),c);
bst::fa[root]=0;
}
}
return 0;
}

洛谷 P3285 / loj 2212 [SCOI2014] 方伯伯的 OJ 题解【平衡树】【线段树】的更多相关文章

  1. 洛谷 P3285 - [SCOI2014]方伯伯的OJ(平衡树)

    洛谷题面传送门 在酒店写的,刚了一整晚终于调出来了-- 首先考虑当 \(n\) 比较小(\(10^5\) 级别)的时候怎么解决,我们考虑将所有用户按排名为关键字建立二叉排序树,我们同时再用一个 map ...

  2. 洛谷P4458 /loj#2512.[BJOI2018]链上二次求和(线段树)

    题面 传送门(loj) 传送门(洛谷) 题解 我果然是人傻常数大的典型啊-- 题解在这儿 //minamoto #include<bits/stdc++.h> #define R regi ...

  3. 洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树

    洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树 题目描述 方伯伯正在做他的 \(Oj\) .现在他在处理 \(Oj\) 上的用户排名问题. \(Oj\) 上注册了 \(n\) 个用户 ...

  4. BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap

    3595: [Scoi2014]方伯伯的Oj Time Limit: 6 Sec  Memory Limit: 256 MBSubmit: 102  Solved: 54[Submit][Status ...

  5. 洛谷 P3919 【模板】可持久化数组(可持久化线段树/平衡树)-可持久化线段树(单点更新,单点查询)

    P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目背景 UPDATE : 最后一个点时间空间已经放大 标题即题意 有了可持久化数组,便可以实现很多衍生的可持久化功能(例如:可持久化并查集 ...

  6. 洛谷 P4125 [WC2012]记忆中的水杉树【扫描线+set+线段树】

    我没有找到能在bzojAC的代码--当然我也WA了--但是我在洛谷过了,那就假装过了吧 minmax线段树一开始写的只能用min更新min,max更新max,实际上是可以互相更新的-- 首先看第二问, ...

  7. luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树

    LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...

  8. 洛谷 P3285 [SCOI2014]方伯伯的OJ

    看到这题,第一眼:平衡树水题,随便做一做好了 然后....我在花了n个小时去调试(维护平衡树父节点)之后,... 调了三个小时后,第一次失败的代码(只能查找排名为k的用户编号,不能根据编号查排名) # ...

  9. [SCOI2014]方伯伯的OJ(线段树)

    方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题.Oj上注册了n个用户,编号为1-n“,一开始他们按照编号排名. 方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为 ...

随机推荐

  1. Mysql加载本地CSV文件

    Mysql加载本地CSV文件 1.系统环境 系统版本:Win10 64位 Mysql版本: 8.0.15 MySQL Community Server - GPL Mysql Workbench版本: ...

  2. CEPH集群RBD快照创建、恢复、删除、克隆(转)

    Ceph支持一个非常好的特性,以COW(写时复制)的方式从RBD快照创建克隆,在Ceph中被称为快照分层.分层特性允许用户创建多个CEPH RBD克隆实例.这些特性应用于OpenStack等云平台中 ...

  3. git post-receive

    1. 将 www 目录设为 777 2. 用git 用户 mkdir 并 git init 3. cat  id_rsa.pub >. authorkeys

  4. 编写高质量代码改善C#程序的157个建议——建议65:总是处理未捕获的异常

    建议65:总是处理未捕获的异常 处理为捕获的异常是每个应用程序具备的基本功能,C#在APPDomain提供了UnhandledException事件来接收未捕获到的异常的通知.常见的应用如下: sta ...

  5. Linux或者window装svn

    Centos7搭建SVN Server手记 安装svn和依赖模块 yum install httpd httpd-devel subversion mod_dav_svn mod_auth_mysql ...

  6. jmeter- 性能测试3:聚合报告(Aggregate Report )

    jmeter-监听器-聚合报告样例: 字段说明: label:请求名称,自己定义的 #Samples:这次测试中一共发出了多少个请求,如果模拟20个用户,每个用户迭代20次,那么就是400(未设置持续 ...

  7. HTML5+CSS3+jQuery Mobile轻松构造APP与移动网站 (陈婉凌) 中文pdf扫描版

    <HTML5+CSS3+jQuery Mobile轻松构造APP与移动网站>以HTML与CSS为主,配合jQuery制作网页,并搭配jQueryMobile制作移动网页,通过具体的范例从基 ...

  8. [Mac] 获取cpu信息

    [Mac] 获取cpu信息 命令行获取cpu信息 sysctl machdep.cpu output like machdep.cpu.tsc_ccc.denominator: 0 machdep.c ...

  9. 数独高阶技巧之八——SDC

    在本系列的第四篇“简单异数链”中,向大家介绍了XY-Wing等一系列Wing类技巧,并提到可以用(拐弯的)数组的观念来理解这些结构,经过第六篇ALS的学习之后,大家回过头再去看Wing,应该可以发现相 ...

  10. Java Spring Bean相关配置

    1.Bean配置信息组成部分: (1)Bean实现类 (2)Bean的属性信息 (3)Bean的依赖关系 (4)Bean的行为配置 2.配置方式: (1)XML配置 (2)注解配置 (3)Java类配 ...