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-”,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和 ...
随机推荐
- 2019 USP Try-outs 练习赛
// 好久没更博客了,最近打了很多场练习赛&校内PK赛,大概自闭忙于补题吧 // 9.26 周四练习赛 A. Kolkhozy 题意 有 n 个数 \(f[i]\) ,有 q 次询问(l, r ...
- python简介与安装
Python简介和环境搭建 于 20世纪80年代末,Guido van Rossum发明了Python,初衷据说是为了打发圣诞节的无趣.1991年首次发布,是ABC语言的继承,同时也是一种脚本语言.取 ...
- sklearn中回归器性能评估方法
explained_variance_score() mean_absolute_error() mean_squared_error() r2_score() 以上四个函数的相同点: 这些函数都有一 ...
- USACO2004 cube stacking /// 带权并查集 oj1302
题目大意: 以N ( 1 ≤ N ≤ 30,000 )个堆栈开始,每个堆栈包含一个单独的立方体.执行P(1≤ P ≤100,000)的操作. 有两种类型的操作:移动和计数. *在移动操作中,将 包含方 ...
- Jmeter---参数化之用户参数
总结: 参数化几次就要设置几个线程,执行的时候,是按顺序执行,下面的请求也会跟着请求
- Number浮点数运算详解
文章来自我的 github 博客,包括技术输出和学习笔记,欢迎star. 一道题 0.1 + 0.2 = ? 在浏览器中测试下计算结果,得到的结果是 0.30000000000000004,并不是理想 ...
- Shell 学习(三)
目录 Shell 学习(三) 流程控制 1 if判断 2 case 语句 3 for循环 4 while 循环 2 read 读取控制台输入 2.1 基本语法 2.2 应用实例 3 函数 3.1 系统 ...
- 字体jquery ---
You don’t need icons! Here are 100+ unicode symbols that you can use Danny Markov December 3rd, 2014 ...
- Nginx启动报错误unlink() “nginx.pid” failed (2: No such file or directory)
在修改了配置文件之后,启动nginx的时候发现,进程已经存在了,但是端口没有监听到. 查看错误日志,有如下错误信息 2015/10/22 21:39:06 [alert] 26434#0: unlin ...
- String = ""和String = null的区别
在这要先说明下 String str;和String str=null;的关系,代码上来说两者几乎不差什么,但是这里String str=null;多了个指向空的引用 而String str ;却只是 ...