BZOJ3595 : [Scoi2014]方伯伯的Oj
由于n很大,有2e8,所以不能直接用splay来维护排名
把splay修改一下
每个节点维护一个区间[l,r],表示编号在[l,r]之间的所有点都在这里
需要支持一个takeout操作:
把编号为k的玩家分离出来,成为一个独立的点
先找到它所在的大点x
splay(x)
然后分裂成1-3个节点
关于如何查找编号为k的玩家在splay中哪个节点
可以开一棵动态开节点的线段树来维护
每次分裂实质就是区间赋值,打标记即可
时间复杂度$O(m\log n)$
写起来真是神清气爽…
#include<cstdio>
#define N 300010
#define M 9000000
const int R=200000000;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int ans;
struct Segmenttree{
int tot,l[M],r[M],tag[M],val[M];
inline void make1(int x,int a,int b,int p){
if(!x)return;
if(a==b)val[x]=p;else tag[x]=p;
}
inline void pb(int x,int a,int b){
if(tag[x]){
int mid=(a+b)>>1;
if(!l[x])l[x]=++tot;
if(!r[x])r[x]=++tot;
make1(l[x],a,mid,tag[x]);
make1(r[x],mid+1,b,tag[x]);
tag[x]=0;
}
}
void change(int x,int a,int b,int c,int d,int p){
if(c<=a&&b<=d){
make1(x,a,b,p);
return;
}
int mid=(a+b)>>1;
pb(x,a,b);
if(c<=mid){
if(!l[x])l[x]=++tot;
change(l[x],a,mid,c,d,p);
}
if(d>mid){
if(!r[x])r[x]=++tot;
change(r[x],mid+1,b,c,d,p);
}
}
int ask(int x,int a,int b,int c){
if(a==b)return val[x];
int mid=(a+b)>>1;
pb(x,a,b);
return c<=mid?ask(l[x],a,mid,c):ask(r[x],mid+1,b,c);
}
inline void init(){
tot=1;
make1(1,1,R,1);
}
}S;
int tot,root,f[N],son[N][2],l[N],r[N],sum[N];
inline void init(int n){
tot=root=l[1]=1;r[1]=n;
}
inline void up(int x){sum[x]=sum[son[x][0]]+sum[son[x][1]]+r[x]-l[x]+1;}
inline void setson(int x,int w,int y){son[x][w]=y;if(y)f[y]=x;}
inline void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][!w];
if(son[x][!w])f[son[x][!w]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;
if(son[z][1]==y)son[z][1]=x;
}
f[x]=f[y];f[y]=x;son[x][!w]=y;up(y);
}
inline void splay(int x){
while(f[x]){
int y=f[x];
if(f[y]){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}
up(root=x);
}
inline int kth(int k){
int x=root,nl,nr;
while(1){
nl=sum[son[x][0]]+1;nr=nl+r[x]-l[x];
if(nl<=k&&k<=nr)return k-nl+l[x];
if(k<nl)x=son[x][0];
else k-=nr,x=son[x][1];
}
}
inline int takeout(int k){//将编号为k的点分离成单点
int x=S.ask(1,1,R,k);
splay(x);
int tl=l[x],tr=r[x],sl=son[x][0],sr=son[x][1];
l[x]=r[x]=k;
if(k!=tl){
int y=++tot;
l[y]=tl;r[y]=k-1;
setson(y,0,sl);
up(y);
S.change(1,1,R,tl,k-1,y);
setson(x,0,y);
}else setson(x,0,sl);
if(k!=tr){
int y=++tot;
l[y]=k+1;r[y]=tr;
setson(y,1,sr);
up(y);
S.change(1,1,R,k+1,tr,y);
setson(x,1,y);
}else setson(x,1,sr);
up(x);
ans=sum[son[x][0]]+1;
return x;
}
inline void top(int k){//把编号为k的点放在首位
int x=takeout(k),a=son[x][0],b=son[x][1],i;
if(b){
f[b]=0;
i=b;
while(son[i][0])i=son[i][0];
splay(i);
setson(i,0,a);
up(i);
}else root=a;
son[x][0]=0;
setson(x,1,root);
up(root=x);
}
inline void bottom(int k){//把编号为k的点放在末尾
int x=takeout(k),a=son[x][0],b=son[x][1],i;
if(b){
f[b]=0;
i=b;
while(son[i][0])i=son[i][0];
splay(i);
setson(i,0,a);
up(i);
}else root=a;
son[x][1]=0;
setson(x,0,root);
up(root=x);
}
inline void change(int k,int p){//把编号为k的点的编号改为p
int x=takeout(k);
l[x]=r[x]=p;
S.change(1,1,R,p,p,x);
}
int n,m,k,x,y;
int main(){
read(n);read(m);
init(n);
S.init();
while(m--){
read(k);read(x);x-=ans;
if(k==1){
read(y);y-=ans;
change(x,y);
printf("%d\n",ans);
}
if(k==2)top(x),printf("%d\n",ans);
if(k==3)bottom(x),printf("%d\n",ans);
if(k==4)printf("%d\n",ans=kth(x));
}
return 0;
}
BZOJ3595 : [Scoi2014]方伯伯的Oj的更多相关文章
- [BZOJ3595][SCOI2014]方伯伯的OJ(裂点Splay)
用一棵Splay按名次维护每个点,其中一个节点对应初始编号连续的一段区间,这样总节点数是$O(m)$的. 对每个编号记录这个点被Splay的那个节点维护,用std::map存储,只记录被修改的点. 每 ...
- 2019.03.28 bzoj3595: [Scoi2014]方伯伯的Oj(splay+map+set)
传送门 题意简述: 给一个有优先级的nnn个人的序列,初始的时候第iii个人排名为iii,现在有mmm个操作,种类如下: 把编号为xxx的改成yyy,输出改前xxx的排名 把编号为xxx放到队首,输出 ...
- 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\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...
- [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-”,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和 ...
随机推荐
- Linux内核之数据双链表
导读 Linux 内核中自己实现了双向链表,可以在 include/linux/list.h 找到定义.我们将会首先从双向链表数据结构开始介绍内核里的数据结构.为什么?因为它在内核里使用的很广泛,你只 ...
- 删除右键ATI CATALYST(R) Control Center的方法
http://share.weiyun.com/c47530d3e44ea15b606d4ba6f1b00a28
- php用soap创建webservice
php提供了一个专门用于soap操作的扩展库,使用该扩展库后 可以直接在php中进行soap操作.下面将介绍soap的基本操作. 一.soap扩展的使用方法 php的soap扩展库通过soap协议实现 ...
- C 结构体小结
看了三天结构体,是时候总结一下了. 关于结构体的声明: struct Student { ]; char sex; int age; ]; }; /*然后定义一个Student 类型的 student ...
- VMware Snapshot 工作原理
VMware中的快照是对VMDK在某个时间点的“拷贝”,这个“拷贝”并不是对VMDK文件的复制,而是保持磁盘文件和系统内存在该时间点的状态,以便在出现故障后虚拟机能够恢复到该时间点.如果对某个虚拟机创 ...
- Unable to mount the CD/DVD image virtualbox解决方法
转自: http://askubuntu.com/questions/321589/unable-to-mount-the-cd-dvd-image-on-the-machine-sandbox
- Selenium测试Ajax程序(转)
上周末参加了Qclub的百度技术沙龙,听了百度的孙景卫讲了Web自动化测试,讲的非常好,然后在小组讨论时又有幸座在了一起.我们讨论的一个内容,就是Ajax应用程序比原来的非Ajax程序更不易测试,这里 ...
- iOS7 status bar 样式问题
在ios7中,有如下status bar 样式 typedef NS_ENUM(NSInteger, UIStatusBarStyle) { UIStatusBarStyleDefault = , / ...
- Linux的文件管理
绝对路径和相对路径: 绝对路径: /home/tony/Desktop 相对路径:Desktop 或者./Desktop不可写成/Desktop(这是绝对路径的写法) 其中.代表本层目录,..代表上层 ...
- AJAX,JSON用户名校验
效果 开发结构 1,src部分有两个包dao和servlet 1.1dao包下有两个数据库工具类文件 SqlHelper.java package org.guangsoft.dao; import ...