loj2212 方伯伯的OJ
题意:

n<=1e8,m<=1e5.
标程:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return x*f;
}
const int N=;
map<int,int> mp;
int sz[N],son[N][],fa[N],L[N],R[N],tot,id[N],n,rt,m,mn,mx,ans,t,rk,x,y,op,g;
void up(int x) {sz[x]=sz[son[x][]]+sz[son[x][]]+R[x]-L[x]+;}
void rot(int &k,int x)
{
int y=fa[x],z=fa[y],l=(son[y][]==x),r=l^;
if (y==k) k=x;else son[z][(son[z][]==y)]=x;
fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
son[y][l]=son[x][r];son[x][r]=y;
up(y);up(x);
}
void spl(int &k,int x)
{
for (int y;x!=k;rot(k,x))
if ((y=fa[x])!=k)
if (son[y][]==x^son[fa[y]][]==y) rot(k,x);else rot(k,y);
}
void ins(int &x,int l,int r,int idx,int f)//在splay的合适位置插入新区间
{
if (!x)
{
L[x=++tot]=l;R[tot]=r;id[tot]=idx;
sz[tot]=r-l+;fa[tot]=f;
return;
}
if (r<L[x]) ins(son[x][],l,r,idx,x);
else ins(son[x][],l,r,idx,x);
up(x);
}
void split(int x,int rk)
{
if (!son[x][]) rt=son[x][],fa[rt]=;//注意换根,保证splay连通
else {
int y=son[x][];
while (son[y][]) y=son[y][];
int z=son[x][];//注意转到根的下一个儿子处,不能转到根
spl(z,y); rt=y;fa[rt]=;
if (son[x][]) son[rt][]=son[x][];fa[son[x][]]=rt;
up(rt);
}
if (L[x]<=rk-) {ins(rt,L[x],rk-,L[x],);spl(rt,tot);}//注意spl前也要判断
if (rk+<=R[x]) {ins(rt,rk+,R[x],rk+,);spl(rt,tot);}
}
int find_rk(int x,int k)//查询rank为k的点(注意rank为k是离散的,不表示排在第k位)
{
if (L[x]<=k&&k<=R[x]) return x;
if (k<L[x]) return find_rk(son[x][],k);
else return find_rk(son[x][],k);
}
int qry_id(int x,int k)//查询rank_k的编号
{
if (k>sz[son[x][]]&&k<=sz[x]-sz[son[x][]])
{
if (L[x]==R[x]) return id[x];
else return L[x]+(k-sz[son[x][]])-;
}
if (k<=sz[son[x][]]) return qry_id(son[x][],k);
else return qry_id(son[x][],k-(sz[x]-sz[son[x][]]));
}
int main()
{
n=read();m=read();
mn=;mx=n;ins(rt,,n,,);//mn从-1往下开始标号,以0来区分是否标记。
while (m--)
{
op=read();x=read()-ans;
if (op==) {printf("%d\n",ans=qry_id(rt,x));continue;}
rk=mp[x];if (!rk) rk=x;
g=find_rk(rt,rk); spl(rt,g);
printf("%d\n",t=sz[son[g][]]+(rk-L[g]+));//离散排名转实际排名
split(g,rk);
if (op==)
{
y=read()-ans;
ins(rt,rk,rk,y,);spl(rt,tot);
mp[y]=rk;mp[x]=;
}else
{
mp[x]=(op==)?--mn:++mx;
ins(rt,mp[x],mp[x],x,);spl(rt,tot);
}
ans=t;
}
return ;
}
易错点:果然又调了很久,不过感觉自己数据分析能力又提高了。。。
1.spl删点换根的时候注意把y旋转到x的右儿子处。如果把y旋转到x处,那么y的右儿子不一定是x,有可能是z,而z的左儿子是x。
2.注意删点函数split中ins之后的splay也要判断是否在区间限制内,反之有可能tot恰好是被删掉的那一个而产生死循环。
3.mn从-1往下开始标号,以0来区分是否标记。
题解:splay+离散排名+区间分裂
一道splay好题。
一开始在纠结怎么实现排名和编号的双转换?
用mp保存每个点的离散排名(就是给不连续参数代替排名)。splay按照实际排名构造,用sz可以查询区间rank_k。对于splay上的每个点保存一段离散排名区间L~R。
排名转编号:排名->sz查询rank_k的点。
编号转排名:编号->离散排名rk->查找该离散排名所在的splay点g->sz[son[g][0]]+rk-L[g]+1.
一般splay是无法保存下所有节点的。
对于动态修改操作,参考noipDay2T3的做法。
一开始只有一个节点。一个节点中保存编号连续的点L~R。如果L!=R,那么这一段的点都没有修改过。执行一个修改操作,就把原来的一个区间删除修改点断开成两个,再插入修改后的点。
对于2和3操作,如果往前面加入的点,离散排名设为--mn,往后加则是++mx。为了节省map空间,只对修改排名的点记录。
这样时空复杂度就只跟操作有关。
也可以建三棵树,往前面加就扔进1树,不变就在2树,往后面加就扔进3树。这样2树中元素太多,可以记录不在2树中的元素(取补)。好像也可以权值线段树。
loj2212 方伯伯的OJ的更多相关文章
- BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap
3595: [Scoi2014]方伯伯的Oj Time Limit: 6 Sec Memory Limit: 256 MBSubmit: 102 Solved: 54[Submit][Status ...
- 「SCOI2014」方伯伯的 OJ 解题报告
「SCOI2014」方伯伯的 OJ 和列队有点像,平衡树点分裂维护即可 但是需要额外用个set之类的对编号查找点的位置 插入完了后记得splay,删除时注意特判好多东西 Code: #include ...
- 方伯伯的OJ ( onlinejudge )
方伯伯的OJ 题目描述 方伯伯正在做他的OJ.现在他在处理OJ 上的用户排名问题. OJ 上注册了n 个用户,编号为1 ∼ n,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用 ...
- luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树
LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...
- 洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树
洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树 题目描述 方伯伯正在做他的 \(Oj\) .现在他在处理 \(Oj\) 上的用户排名问题. \(Oj\) 上注册了 \(n\) 个用户 ...
- [SCOI2014]方伯伯的OJ(线段树)
方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题.Oj上注册了n个用户,编号为1-n“,一开始他们按照编号排名. 方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为 ...
- [SCOI2014]方伯伯的OJ
看到这道题的第一想法就是要用FHQ treap 过了这道题...于是至今尚未成功(华丽的 T 掉了 (╯‵□′)╯︵┻━┻ ).于是附个地址. 然后水一波博客. 题意简介 emmmm...方伯伯脑抽做 ...
- 洛谷 P3285 / loj 2212 [SCOI2014] 方伯伯的 OJ 题解【平衡树】【线段树】
平衡树分裂钛好玩辣! 题目描述 方伯伯正在做他的 OJ.现在他在处理 OJ 上的用户排名问题. OJ 上注册了 \(n\) 个用户,编号为 \(1\sim n\),一开始他们按照编号排名.方伯伯会按照 ...
- BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常
Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-”,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和 ...
随机推荐
- redis和redis php扩展安装
redis的源码安装 wget http://download.redis.io/redis-stable.tar.gz tar -zxvf redis-stable.tar.gz cd redis- ...
- seo具备的条件
对于SEO这行业,许多想学习这一行,但是并非每一个人都有这样才能.因为SEO份这行靠是真材实料并非虚拟人才.现在找到高工资的SEO人才需要 有三年以上经验,熟悉PHP.html.asp.java等等这 ...
- Jmeter----参数化之csv文件
用户编码:一般不用填写,如果有中文的时候,需要填写,填写utf-8就可以 变量名词:是指的把数据保存在什么变量里面,其他的默认就好了 Http请求和用户参数设置的一样
- Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR tensorflow-1.13.1和1.14windows版本目前不支持CUDA10.0
报错出现 Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR tensorflow-1.13.1和1.14windows版本目前不支持 ...
- Impala系统架构
- META标签的定义与使用(一、HTTP标题信息(http-equiv))
META标签分两大部分:HTTP标题信息(http-equiv)和页面描述信息(name). 一.http-equiv类似于HTTP的头部协议,它回应给浏览器一些有用的信息,以帮助正确和精确地显示网页 ...
- matlab 求已知概率密度函数的随机数生成
N=10000; %需要随机数的个数 a=zeros(N,1); %存放随机数的数列 n=0; f1=@(t) 1./(1.2*pi*(1+5*(t-7.3).^2)); f2=@(t) 1./(1. ...
- 深度探索C++对象模型之第一章:关于对象之对象的差异
一.三种程序设计范式: C++程序设计模型支持三种程序设计范式(programming paradiams). 程序模型(procedural model) char boy[] = "cc ...
- yii2.0 数据库查询操作
User::find()->all(); 此方法返回所有数据: User::findOne($id); 此方法返回 主键 id=1 的一条数据(举个例子): User:: ...
- 配置类一@CrossOrigin
@CrossOrigin是用来处理跨域请求的注解 跨域:指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制. 所谓同源是指,域名,协议,端口 ...