[SCOI2014]方伯伯的OJ(线段树)
方伯伯正在做他的Oj。现在他在处理Oj上的用户排名问题。Oj上注册了n个用户,编号为1~n“,一开始他们按照编号排名。
方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号:
1.操作格式为1 x y,意味着将编号为x的用户编号改为y,而排名不变,执行完该操作后需要输出该用户在队列中的位置,数据保证x必然出现在队列中,同时,1是一个当前不在排名中的编号。
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现在你截获了方伯伯的所有操作,希望你能给出结果。
Solution
调了一晚上。。。菜的不行。
因为数列每次只会变化一个数,所以可以不用splay或fhqtreap,用一颗动态开点线段树就可以完成。
因为我们的移动只关于先插和后插,所以我们线段树的区间为m+n+m对于一个移动,我们先把该点在对应位置删除,再将该数插入前/后对应位置。
与此同时,我们开两个map,一个储存编号对应的位置,一个储存位置对应的编号。
Code
#include<iostream>
#include<cstdio>
#include<map>
#define ls tr[cnt].l
#define rs tr[cnt].r
#define N 200002
using namespace std;
map<int,int>mp,anti_mp;
int tot,id,ans,n,m,root,h,t,x,y;
struct seg{
int l,r,num;
bool la;
}tr[N*];
inline int rd(){
int x=;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c)){
x=(x<<)+(x<<)+(c^);
c=getchar();
}
return x;
}
inline void pushdown(int cnt,int l1,int l2){
if(!ls)ls=++tot;if(!rs)rs=++tot;
tr[ls].num=l1;tr[rs].num=l2;
tr[cnt].la=;tr[ls].la=tr[rs].la=;
}
void add(int &cnt,int l,int r,int x,int tag,int rk){
if(!cnt)cnt=++tot;
if(l==r){
if(tag<)ans=rk+,anti_mp.erase(l);
else anti_mp[l]=id;
tr[cnt].num-=tag;
return;
}
int mid=(l+r)>>;
if(tr[cnt].la)pushdown(cnt,mid-l+,r-mid);
if(mid>=x)add(ls,l,mid,x,tag,rk);
else add(rs,mid+,r,x,tag,rk+mid-l+-tr[ls].num);
tr[cnt].num=tr[ls].num+tr[rs].num;
}
void find(int &cnt,int l,int r,int rk){
if(!cnt)cnt=++tot;
if(l==r){
if(anti_mp.find(l)!=anti_mp.end())ans=anti_mp[l];else ans=l-m;
return;
}
int mid=(l+r)>>;
if(tr[cnt].la)pushdown(cnt,mid-l+,r-mid);
int num=mid-l+-tr[ls].num;
if(num>=rk)find(ls,l,mid,rk);
else find(rs,mid+,r,rk-num);
}
void gai(int &cnt,int l,int r,int L,int R){
if(!cnt)cnt=++tot;
if(l>=L&&r<=R){
tr[cnt].num=r-l+;
tr[cnt].la=;
return;
}
int mid=(l+r)>>;
if(mid>=L)gai(ls,l,mid,L,R);
if(mid<R)gai(rs,mid+,r,L,R);
tr[cnt].num=tr[ls].num+tr[rs].num;
}
void upd(int &cnt,int l,int r,int x,int y,int rk){
if(!cnt)cnt=++tot;
if(l==r){
anti_mp[l]=y;ans=rk+;
return;
}
int mid=(l+r)>>;
if(tr[cnt].la)pushdown(cnt,mid-l+,r-mid);
if(mid>=x)upd(ls,l,mid,x,y,rk);
else upd(rs,mid+,r,x,y,rk+mid-l+-tr[ls].num);
}
int main(){
n=rd();m=rd();
gai(root,,n+*m,,m);
gai(root,,n+*m,n+m+,n+m*);
h=m+;t=n+m;
for(int i=;i<=m;++i){
int tag=rd();x=rd()-ans;
if(tag==){
y=rd()-ans;
int pos;
if(mp.find(x)!=mp.end())pos=mp[x];
else pos=x+m;
mp[y]=pos;
upd(root,,n+*m,pos,y,);
}
else if(tag==){
int pos;
if(mp.find(x)!=mp.end())pos=mp[x];
else pos=x+m;
if(anti_mp.find(pos)!=anti_mp.end())id=anti_mp[pos];
else id=x;
add(root,,n+*m,pos,-,);
add(root,,n+*m,--h,,);
mp[x]=h;
}
else if(tag==){
int pos;
if(mp.find(x)!=mp.end())pos=mp[x];
else pos=x+m;
if(anti_mp.find(pos)!=anti_mp.end())id=anti_mp[pos];
else id=x;
add(root,,n+*m,pos,-,);
add(root,,n+*m,++t,,);
mp[x]=t;
}
else find(root,,n+*m,x);
printf("%d\n",ans);
}
return ;
}
[SCOI2014]方伯伯的OJ(线段树)的更多相关文章
- BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap
3595: [Scoi2014]方伯伯的Oj Time Limit: 6 Sec Memory Limit: 256 MBSubmit: 102 Solved: 54[Submit][Status ...
- 洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树
洛谷P3285 [SCOI2014]方伯伯的OJ 动态开点平衡树 题目描述 方伯伯正在做他的 \(Oj\) .现在他在处理 \(Oj\) 上的用户排名问题. \(Oj\) 上注册了 \(n\) 个用户 ...
- luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树
LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...
- 洛谷 P3285 / loj 2212 [SCOI2014] 方伯伯的 OJ 题解【平衡树】【线段树】
平衡树分裂钛好玩辣! 题目描述 方伯伯正在做他的 OJ.现在他在处理 OJ 上的用户排名问题. OJ 上注册了 \(n\) 个用户,编号为 \(1\sim n\),一开始他们按照编号排名.方伯伯会按照 ...
- [SCOI2014]方伯伯的OJ
看到这道题的第一想法就是要用FHQ treap 过了这道题...于是至今尚未成功(华丽的 T 掉了 (╯‵□′)╯︵┻━┻ ).于是附个地址. 然后水一波博客. 题意简介 emmmm...方伯伯脑抽做 ...
- BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常
Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-”,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和 ...
- BZOJ3595 : [Scoi2014]方伯伯的Oj
由于n很大,有2e8,所以不能直接用splay来维护排名 把splay修改一下 每个节点维护一个区间[l,r],表示编号在[l,r]之间的所有点都在这里 需要支持一个takeout操作: 把编号为k的 ...
- 洛谷 P3285 [SCOI2014]方伯伯的OJ
看到这题,第一眼:平衡树水题,随便做一做好了 然后....我在花了n个小时去调试(维护平衡树父节点)之后,... 调了三个小时后,第一次失败的代码(只能查找排名为k的用户编号,不能根据编号查排名) # ...
- [Scoi2014]方伯伯的OJ(动态开点splay)
开始没看数据范围差点以为是这题了:https://www.cnblogs.com/hfctf0210/p/10911340.html 然后看到n<=1e8,怎么这么大? 所以这题需要用动态开点线 ...
随机推荐
- jvisualvm中VisualGC插件提示:不受此JVM支持
Visual GC插件「不受此JVM支持」问题 - djp567的博客 - CSDN博客https://blog.csdn.net/djp567/article/details/78662047 jv ...
- C#设计模式之7:适配器模式
适配器模式 使用适配器模式的一个重要的点是首先要识别出什么代码(接口)是已经存在的,什么代码(接口)是新的,需要去适配的.适配器的作用是让旧的(现有的)接口能够匹配新的系统(要去适配的). 比如有下面 ...
- innerText兼容问题处理
IE.Safari.Opera和Chrome支持innerText属性.低版本的火狐浏览器不支持,但支持作用类似的textContent属性.textContent是DOM3级规定的一个属性,而且也得 ...
- mysql逻辑架构
逻辑架构图 MySQL有点与众不同,它的逻辑架构可以在多种不同的场景中应用并发挥良好的作用.主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取相分离.这种架构 ...
- Golang的聊天服务器实践(群聊,广播)(一)
其实从上学开始就一直想写一个im. 最近深入go,真是学会了太多,感觉人森虽然苦短,但是也不能只用python.很多知识是不用编译型语言无法了解的. 该来的还是会来,现在会一步一步用go把这个服务器完 ...
- 将大数组里面的小数组平行展开的实现(Making a flat list out of list of lists in Python)
今天在生成数据的时候遇到了这个需求,其实写一个for循环可以很容易解决这个问题,但是无论是性能还是酷炫程度上都不行 所以顺手搜索了一下. 例子是将 l = [[1, 2, 3], [4, 5, 6], ...
- umount -fl用法
umount, 老是提示:device is busy, 服务又不能停止的.可以用"umount -fl"解决! 挂载: mount - mount a filesystem mo ...
- python数学第七天【期望的性质】
- shiro使用ajax登陆实现,success但页面无法跳转的问题
首先:简述一下登陆的后台流程 页面提交——>对应controller中的方法——>对应Realm认证——>controller返回 json 这样,无论成功与否,都有返回值,可以用 ...
- adoquery怎样判断数据在缓存中有修改啊
ADOQry.Filtered:=false; ADOQry.Filtered:=true; ADOQry.FilterGroup:=fgPendingRecords ;Fil ...