方伯伯的OJ

题目描述

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

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

1. 操作格式为1 x y,意味着将编号为的用户编号改为y,而排名不变,执行完该操作后需要输出该用户在队列中的位置,数据保证必然出现在队列中, 同时是一个当前不在排名中的编号。

2. 操作格式为2 x,意味着将编号为的用户的排名提升到第一位,执行完该操作后需要输出执行该操作前编号为用户的排名。

3. 操作格式为3 x,意味着将编号为的用户的排名降到最后一位,执行完该操作后需要输出执行该操作前编号为用户的排名。

4. 操作格式为4 k,意味着查询当前排名为的用户编号,执行完该操作后需要输出当前操作用户的编号。

但同时为了防止别人监听自己的工作,方伯伯对他的操作进行了加密,即将四种操作的格式分别改为了:

a y a

a

a

a

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

例如:

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

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

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

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

输入格式

输入的第1 行包含2 个用空格分隔的整数m,表示初始用户数和操作数。

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

输出格式

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

样例

样例输入

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

数据范围与提示

【数据范围】
对于10% 的数据,1 ≤ n ≤ 10^3
对于40% 的数据,1 ≤ n ≤ 10^5
对于100% 的数据,1 ≤ n ≤ 10^8,1 ≤ m ≤ 105
输入保证对于所有的操作1,2,3,x 必然已经出现在队列中,同时对于所有操作1,1 ≤ y ≤ 2 ×10^8,并且y 没有出现在队列中。对于所有操作4,保证1 ≤ k ≤ n。

solution
可以发现1e8的数据啥也开不起来。
我们考虑用 splay 维护一段区间,这样的状态数是m了。
还是以splay的大小关系表示排名,节点维护区间长度。
对于1操作,我们用两个map将编号对应到 1~1e8
对于2.3操作,我们找到包含这个点的区间。然后把它拆成三块。
对于4操作,splay上找k大即可。
现在还剩一个问题,怎么找到包含某个点的区间。
邵神犇:用一个set把当前所有区间的左端点存起来,每次找第一个包含它的。(%%%
那就解决啦。
 
然而这题全是细节。。。
1.找第k大时找到了也要减左儿子
if(tr[ls].sz>=x)k=ls;
else if(tr[ls].sz+tr[k].r-tr[k].l+>=x){x-=tr[ls].sz;break;}
else x-=tr[ls].sz+tr[k].r-tr[k].l+,k=tr[k].ch[];

2.insert完要维护一整条链。

3.区间的size为r-l+1

4.根的前驱不是左儿子!!根的后驱不是右儿子!!(可能是我傻逼)

5.注意分讨x=l x=r x=l=r的特殊情况

6.节点开2m~3m

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
using namespace std;
int n,m,rt,ans,cnt;
struct node{
int sz,l,r,ch[],f;
}tr[];
set<int>s;
map<int,int>ls,dy,id;
void print_a(int k){
if(!k)return;
print_a(tr[k].ch[]);
for(int i=tr[k].l;i<=tr[k].r;i++)printf("%d ",i);
print_a(tr[k].ch[]);
}
bool get(int x){return tr[tr[x].f].ch[]==x;}
void wh(int x){
tr[x].sz=tr[tr[x].ch[]].sz+tr[tr[x].ch[]].sz+tr[x].r-tr[x].l+;
}
void rotate(int x){
int y=tr[x].f,z=tr[y].f;
int wx=get(x),wy=get(y);
tr[z].ch[wy]=x;tr[x].f=z;
tr[y].ch[wx]=tr[x].ch[wx^];tr[tr[x].ch[wx^]].f=y;
tr[x].ch[wx^]=y;tr[y].f=x;
wh(y);wh(x);
}
void splay(int x,int g){
while(tr[x].f!=g){
int y=tr[x].f,z=tr[y].f;
if(z!=g)rotate(get(x)==get(y)?y:x);
rotate(x);
}
if(!g)rt=x;
}
void ask(int t){
set<int>::iterator pos;
pos=s.upper_bound(t);pos--;
int k=id[*pos];
//cout<<"aaa "<<t<<' '<<*pos<<' '<<k<<' '<<tr[k].l<<' '<<tr[k].r <<endl;
splay(k,);
ans=tr[tr[rt].ch[]].sz;
ans+=t-(*pos)+;
printf("%d\n",ans);
}
void insert_Front(int x){
int k=rt;
while(tr[k].ch[])k=tr[k].ch[];
int p=++cnt;
tr[p].l=tr[p].r=x;tr[p].sz=;
tr[k].ch[]=p;tr[p].f=k;
for(int i=p;i;i=tr[i].f)wh(i);
s.insert(x);id[x]=cnt;
splay(p,);
}
void insert_Bottom(int x){
int k=rt;
while(tr[k].ch[])k=tr[k].ch[];
int p=++cnt;
tr[p].l=tr[p].r=x;tr[p].sz=;
tr[k].ch[]=p;tr[p].f=k;
for(int i=p;i;i=tr[i].f)wh(i);
s.insert(x);id[x]=cnt;
splay(p,);
//cout<<p<<' '<<tr[p].l<<' '<<tr[p].r<<' '<<tr[p].f<<endl;
}
void add(int x,int opt){
int l=tr[rt].l,r=tr[rt].r;
if(l==r){
int ls=tr[rt].ch[],rs=tr[rt].ch[];
if(!ls)rt=rs,tr[rs].f=;
else if(!rs)rt=ls,tr[ls].f=;
else {
while(tr[ls].ch[])ls=tr[ls].ch[];
while(tr[rs].ch[])rs=tr[rs].ch[];
splay(ls,);splay(rs,ls);
//print_a(rt);puts("");puts("------");
tr[tr[rt].ch[]].ch[]=;
wh(tr[rt].ch[]);wh(rt);
//print_a(rt);puts("");puts("------");
}
}
else if(x==l){ tr[rt].l=x+,wh(rt);
s.insert(x+);id[x+]=rt;
}
else if(x==r){
tr[rt].r=x-,wh(rt);
}
else {
int k=++cnt;
tr[k].l=x+;tr[k].r=tr[rt].r;
tr[rt].r=x-;
int rs=tr[rt].ch[];
if(rs){tr[k].ch[]=rs;tr[rs].f=k;}
tr[rt].ch[]=k;tr[k].f=rt;
wh(k);wh(rt);
//printf("id%d l=%d r=%d rs=%d k=%d\n",rt,tr[rt].l,tr[rt].r,tr[rt].ch[1],k);
//printf("kid%d kl=%d lr=%d\n",k,tr[k].l,tr[k].r);
s.insert(x+);id[x+]=k; }
if(!opt)insert_Front(x);
else insert_Bottom(x);
}
void Kth(int x){
int k=rt;
while(){
//printf("k:%d l=%d r=%d\n",k,tr[k].l,tr[k].r);
int ls=tr[k].ch[];
//printf("sz:%d\n",tr[ls].sz);
if(tr[ls].sz>=x)k=ls;
else if(tr[ls].sz+tr[k].r-tr[k].l+>=x){x-=tr[ls].sz;break;}
else x-=tr[ls].sz+tr[k].r-tr[k].l+,k=tr[k].ch[];
}
//cout<<tr[k].l<<' '<<x<<endl;
int f=tr[k].l+x-;
ans=dy[f];if(!ans)ans=f;
printf("%d\n",ans);
} int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cin>>n>>m;
rt=;cnt=;
tr[].l=,tr[].r=n,tr[].sz=n;
s.insert();id[]=;
ans=;
//print_a(rt);puts("");
for(int i=,op,x,y;i<=m;i++){
scanf("%d%d",&op,&x);x-=ans;
if(op==){
scanf("%d",&y);
y-=ans;
int t=ls[x];if(!t)t=x;
ls[y]=t;dy[t]=y;
ask(t);
}
if(op==){
int t=ls[x];if(!t)t=x;
ask(t);add(t,);
}
if(op==){
int t=ls[x];if(!t)t=x;
ask(t);add(t,);
}
if(op==){
Kth(x);
}
//cout<<"root "<<rt<<endl;
//print_a(rt);puts("");puts("------");
}
return ;
}
 

方伯伯的OJ ( onlinejudge )的更多相关文章

  1. SCOI2014 方伯伯的OJ onlinejudge

    终于用自己的方法水过去了. 本地测慢的一组要三四秒,一共要十几秒,BZOJ貌似一共只让跑6s,于是就还T着的. 一开始没看n<=1e8,想的直接splay+map(splay维护名次,map维护 ...

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

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

  3. 「SCOI2014」方伯伯的 OJ 解题报告

    「SCOI2014」方伯伯的 OJ 和列队有点像,平衡树点分裂维护即可 但是需要额外用个set之类的对编号查找点的位置 插入完了后记得splay,删除时注意特判好多东西 Code: #include ...

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

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

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

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

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

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

  7. [SCOI2014]方伯伯的OJ

    看到这道题的第一想法就是要用FHQ treap 过了这道题...于是至今尚未成功(华丽的 T 掉了 (╯‵□′)╯︵┻━┻ ).于是附个地址. 然后水一波博客. 题意简介 emmmm...方伯伯脑抽做 ...

  8. 洛谷 P3285 / loj 2212 [SCOI2014] 方伯伯的 OJ 题解【平衡树】【线段树】

    平衡树分裂钛好玩辣! 题目描述 方伯伯正在做他的 OJ.现在他在处理 OJ 上的用户排名问题. OJ 上注册了 \(n\) 个用户,编号为 \(1\sim n\),一开始他们按照编号排名.方伯伯会按照 ...

  9. BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常

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

随机推荐

  1. BZOJ1854: [Scoi2010]游戏(二分图匹配)

    题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...

  2. 如何在RedHat 7.0系统中安装mysql 5.7.22

    如何在RedHat 7.0系统中安装mysql 5.7.22 今天给大家介绍一下如何安装mysql5.7,在安装之前,首先要查看的是,你的系统中有没有已经安装过的情况.键入rpm -qa|grep m ...

  3. Python 遗传算法实现字符串

    Python 遗传算法实现字符串 流程 1. 初始化 2. 适应度函数 3. 选择 4. 交叉 5. 变异 适应度函数计算方法 计算个体间的差:分别计算每个元素与目标元素的差取平方和 种群:计算总体均 ...

  4. php扩展开发-常量

    //常量在内核中的结构 typedef struct _zend_constant { zval value; int flags; char *name; uint name_len; int mo ...

  5. C指针——简单总结

    简介: 指针变量在使用前,必须指向具体的有效的内存单元 指针变量在使用前不但要定义还要初始化 四个方面:指针的类型,指针指向的类型,指针的值或者指针所指向的内存区,指针本身所占的内存区 int *pt ...

  6. No module named 'PyQt5.sip'

    使用pyinstaller打包python文件为windows可执行程序可能遇到的问题 pyinstaller yourprogram.py打包的程序双击打开一闪而过,提示上面标题的错误 把pycom ...

  7. C语言指针篇(二)多级指针

        多级指针         多级指针常常使用于数组.这里仅仅介绍一下它长什么样,后文会再次详细对比使用.         多级指针呢,常见的有二级指针.见图.             二级指针的 ...

  8. HDU 6386 Age of Moyu

    Problem Description Mr.Quin love fishes so much and Mr.Quin’s city has a nautical system,consisiting ...

  9. ISCSI网络存储

    ISCSI(iSCSI,Internet Small Computer System Interface) iSCSI技术实现了物理硬盘设备与TCP/IP网络协议的相互结合,使得用户可以通过互联网方便 ...

  10. Android 懒加载简单介绍

    1.懒加载介绍 1.1.效果预览 1.2.效果讲解 当页面可见的时候,才加载当前页面. 没有打开的页面,就不会预加载. 说白了,懒加载就是可见的时候才去请求数据. 1.3.懒加载文章传送门 参考文章: ...