看到这道题的第一想法就是要用FHQ treap 过了这道题...于是至今尚未成功(华丽的 T 掉了 (╯‵□′)╯︵┻━┻ )。于是附个地址。

然后水一波博客。

题意简介

emmmm...方伯伯脑抽做了个 oj ,然后想要在对 oj 上的 1~n 编号的用户乱来(并且还对他的乱来操作进行了加密)。你需要维护一棵平衡树完成方伯伯的一波操作

你的平衡树需要支持这些操作: 1. 修改编号; 2. 把一个人放到树的最左边; 3. 把一个人放到树的最右边;4.输出一个排名对应的编号。

题目分析

然后这道题非常坑,要用 map 记录每个节点对应区间右端点的对应节点编号 (听起来很绕,其实就是: 设某节点对应区间右端点为 R , 该节点编号为 p , 那么我们用的map 的 first key 就是 R ,second key 是 p),然后用找某个编号所在的节点用 lower_bound 就好了(才知道map是可以 lower bound 的,并且是以第一关键字作比较的)。我记得有看到用另一种利用 map 的方法,那好像是 普通 treap (splay应该也能用啊)的,而且节点维护的区间也有点混乱...就是这个

Splay 做法

  1 //by Judge
2 #include<iostream>
3 #include<cstdio>
4 #include<map>
5 using namespace std;
6 const int M=5e5+111;
7 //#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
8 char buf[1<<21],*p1=buf,*p2=buf;
9 inline int read(){
10 int x=0,f=1; char c=getchar();
11 for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
12 for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
13 }
14 char sr[1<<21],z[20];int C=-1,Z;
15 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
16 inline void print(int x){
17 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
18 while(z[++Z]=x%10+48,x/=10);
19 while(sr[++C]=z[Z],--Z);sr[++C]='\n';
20 }
21 int n,m,cnt,ans,root;
22 map<int,int> mp;
23 struct Node{
24 int l,r,siz,fa,ch[2];
25 }t[M];
26 inline int newnode(int x,int y){ int u=++cnt; t[u].siz=y-x+1,t[u].l=x,t[u].r=y; return u; }
27 inline void pushup(int x){ t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+t[x].r-t[x].l+1; }
28 inline void rotate(int x){
29 int y=t[x].fa,z=t[y].fa,sn=t[y].ch[1]==x;
30 t[x].fa=z; if(z) t[z].ch[t[z].ch[1]==y]=x;
31 t[y].ch[sn]=t[x].ch[!sn],t[t[y].ch[sn]].fa=y;
32 t[y].fa=x,t[x].ch[!sn]=y,pushup(y);
33 }
34 inline void splay(int x,int to){
35 while(t[x].fa^to){
36 int y=t[x].fa,z=t[y].fa;
37 if(z!=to) rotate((t[z].ch[0]==y)^(t[y].ch[0]==x)?x:y);
38 rotate(x);
39 } pushup(x); if(!to) root=x;
40 }
41 inline int query(int x){ splay(x,0); return t[x].siz-t[t[x].ch[1]].siz; }
42 inline int get_id(int k){ //查询排名为 k 的人的编号
43 int now=root;
44 while(k){
45 int sum=t[t[now].ch[0]].siz+t[now].r-t[now].l+1;
46 if(t[t[now].ch[0]].siz<k && k<=sum){
47 k-=t[t[now].ch[0]].siz; break;
48 } else if(sum<k) k-=sum,now=t[now].ch[1];
49 else now=t[now].ch[0];
50 } return t[now].l+k-1;
51 }
52 inline void erase(int x){ //删除节点信息
53 int pre=t[x].ch[0],nxt=t[x].ch[1];
54 while(t[pre].ch[1]) pre=t[pre].ch[1];
55 while(t[nxt].ch[0]) nxt=t[nxt].ch[0];
56 if(!pre && !nxt) return (void)(root=0);
57 if(!pre) splay(nxt,root),t[root=nxt].fa=0;
58 else if(!nxt) splay(pre,root),t[root=pre].fa=0;
59 else splay(pre,0),splay(nxt,pre),t[nxt].ch[0]=0,pushup(nxt),pushup(pre);
60 t[x].ch[0]=t[x].ch[1]=0,t[x].siz=1; //不知道为什么这里不写会 T (懒得想咯应该是编号改完可能会改回来的问题吧)
61 }
62 inline void push_front(int x){ //插头
63 if(!root) return (void)(root=x); int fa=root;
64 while(t[fa].ch[0]) ++t[fa].siz,fa=t[fa].ch[0];
65 ++t[fa].siz,t[fa].ch[0]=x,t[x].fa=fa,splay(x,0);
66 }
67 inline void push_back(int x){ //插尾
68 if(!root) return (void)(root=x); int fa=root;
69 while(t[fa].ch[1]) ++t[fa].siz,fa=t[fa].ch[1];
70 ++t[fa].siz,t[fa].ch[1]=x,t[x].fa=fa,splay(x,0);
71 }
72 inline void split(int x,int id){ //拆出节点
73 int L=t[x].l,R=t[x].r,ls,rs;
74 if(L==R) return ; //不用拆
75 if(L==id){ //最左端
76 mp[R]=rs=++cnt,mp[id]=x;
77 t[rs].ch[1]=t[x].ch[1];
78 t[t[rs].ch[1]].fa=rs;
79 t[x].ch[1]=rs,t[rs].fa=x;
80 t[rs].l=L+1,t[rs].r=R,t[x].r=L;
81 pushup(rs),pushup(x);
82 } else if(R==id){ //最右端
83 mp[R-1]=ls=++cnt,mp[id]=x;
84 t[ls].ch[0]=t[x].ch[0];
85 t[t[ls].ch[0]].fa=ls;
86 t[x].ch[0]=ls,t[ls].fa=x;
87 t[ls].l=L,t[ls].r=R-1,t[x].l=R;
88 pushup(ls),pushup(x);
89 } else{ //在中间
90 mp[id]=x,mp[id-1]=ls=++cnt,mp[R]=rs=++cnt;
91 t[ls].ch[0]=t[x].ch[0],t[rs].ch[1]=t[x].ch[1];
92 t[t[ls].ch[0]].fa=ls,t[t[rs].ch[1]].fa=rs;
93 t[x].ch[0]=ls,t[x].ch[1]=rs,t[ls].fa=t[rs].fa=x;
94 t[x].l=t[x].r=id,t[ls].l=L,t[ls].r=id-1,t[rs].l=id+1,t[rs].r=R;
95 pushup(ls),pushup(rs),pushup(x);
96 }
97 }
98 signed main() {
99 n=read(),m=read(),
100 mp[n]=root=newnode(1,n);
101 for(int x,y,pos,opt;m;--m){
102 opt=read();
103 switch(opt){
104 case 1:
105 x=read()-ans,y=read()-ans;
106 pos=mp.lower_bound(x)->second; //map 里面找节点编号
107 split(pos,x),ans=query(pos); //拆出节点查排名
108 t[pos].l=t[pos].r=y,mp[y]=pos; //修改信息输答案
109 print(ans); break;
110 case 2:
111 x=read()-ans, pos=mp.lower_bound(x)->second;
112 split(pos,x),ans=query(pos),erase(pos); //拆除节点再删除
113 push_front(pos),print(ans); break; //节点重新加入树
114 case 3:
115 x=read()-ans, pos=mp.lower_bound(x)->second;
116 split(pos,x),ans=query(pos),erase(pos);
117 push_back(pos),print(ans); break;
118 case 4:
119 x=read()-ans,ans=get_id(x),print(ans); break; //询问编号直输出
120 }
121 } Ot(); return 0;
122 }

FHQ treap

[SCOI2014]方伯伯的OJ的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. SCOI2014 方伯伯的OJ onlinejudge

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

  8. 【bzoj 3595】: [Scoi2014]方伯伯的Oj

    传送门&& 原题解 蒟蒻终于做到一道方伯伯的题了…… 调了一个上午一直TLE(发现自己打了好久的splay板子竟然是错的这种丢人事情我就不说了) 很明显,要建两棵树,$T1$维护排名, ...

  9. BZOJ3595 : [Scoi2014]方伯伯的Oj

    由于n很大,有2e8,所以不能直接用splay来维护排名 把splay修改一下 每个节点维护一个区间[l,r],表示编号在[l,r]之间的所有点都在这里 需要支持一个takeout操作: 把编号为k的 ...

随机推荐

  1. 谈谈关于PHP连接数据库的两种方法(PDO&Mysqli)

    前言:在我们之前学习sql语句的时候都是停留在黑窗口的,怎样才能让mysql与程序代码发生联系呢?此时PDO和Mysqli应运而生,为了解决这个问题 (一)开启其中(pdo或者mysqli)的php扩 ...

  2. golang实现tcp编程

    实现简单的tcp服务 package main import ( "fmt" "net" ) func main() { fmt.Println("服 ...

  3. [ASNI C] [常用宏定义] [define技巧]

    1. 打印变量名及其值 #define Inquire(var, mode) fprintf(stdout, #var" = "#mode". \n", var ...

  4. 数据结构Java实现02----单向链表的插入和删除

    文本主要内容: 链表结构 单链表代码实现 单链表的效率分析 一.链表结构: (物理存储结构上不连续,逻辑上连续:大小不固定)            概念: 链式存储结构是基于指针实现的.我们把一个数据 ...

  5. Android中的分层----service 层,domain层,dao 层,action层等设计

    service 层 服务层:直接为客户端提供的服务或功能.也是系统所能对外提供的功能. domain层 领域层:系统内的领域活动,存放实体. dao 层 持久层,DB操作都写在这里,数据访问对象,通过 ...

  6. 2018年度 35 个最好用 Vue 开源库

    在本文中,我们将推荐一些非常好用的 Vue 相关的开源项目.无论是开发新手还是经验丰富的老手,我们都喜欢开源软件包.对于开发者来说,如果没有这些开源软件包,很难想象我们的生活会变得多么疲惫不堪,而且靠 ...

  7. 使用Verilog HDL语言注意事项

    1.wire和reg区别,输入输出是wire型,表示硬件线的连接,要在always模块里被赋值需要中间reg型变量,两者通过: assign 输入/输出=reg型中间变量 2.case的default ...

  8. IDApython教程(四)

    前三部分已经验证了用IDAPython能够让工作变的更简单,这一部分让我们看看逆向工程师如何使用IDAPython的颜色和强大的脚本特性. 分析者经常需要面对越来越复杂的代码,而且有时候无法轻易看出动 ...

  9. linux 测试 get 请求 跳过SSL证书验证

    Linux 下测试 get 请求: curl : curl "http://www.qq.com" # 标准输出页面内容 curl -i "http://www.qq.c ...

  10. K - Video Reviews Gym - 101755K (二分)

    题目链接: K - Video Reviews Gym - 101755K 题目大意: 一家公司想让个人给他们的产品评论,所以依次去找这个人,第i个人会评论当且仅当已经有个人评论或他确实对这个产品感兴 ...