2019.03.28 bzoj3595: [Scoi2014]方伯伯的Oj(splay+map+set)
传送门
题意简述:
给一个有优先级的nnn个人的序列,初始的时候第iii个人排名为iii,现在有mmm个操作,种类如下:
- 把编号为xxx的改成yyy,输出改前xxx的排名
- 把编号为xxx放到队首,输出改前xxx的排名
- 把编号为xxx放到队尾,输出改前xxx的排名
- 输出排名为xxx的编号。
强制在线,n≤1e8,m≤1e5n\le1e8,m\le1e5n≤1e8,m≤1e5
思路:
本蒟蒻的第一道splay!splay!splay!过了好激动qwqqwqqwq
由于nnn较大直接上平衡树ttt飞,考虑到操作数少,如果我们把未修改的段压成一个点然后用splaysplaysplay维护,每次就只会最多把一个分成333个,最终节点数只有3e53e53e5个就可以过了,于是用setsetset和mapmapmap辅助维护一下即可。
注意细节。
然而博主的常数太大bzoj过不了,实测1s能跑过
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int N=3e5+5;
typedef pair<int,int> pii;
map<pii,int>S;
map<int,int>mp,imp;
set<int>upd;
typedef set<int>::iterator It;
int n,m,tt=1;
namespace Splay{
#define lc (son[p][0])
#define rc (son[p][1])
int tot=0,rt=0,fa[N],son[N][2],L[N],R[N],siz[N],sum[N];
inline int which(const int&x){return x==son[fa[x]][1];}
inline void pushup(int p){siz[p]=siz[lc]+1+siz[rc],sum[p]=sum[lc]+(R[p]-L[p]+1)+sum[rc];}
inline int build(int l,int r,int ft,int t){
fa[++tot]=ft,ft?son[ft][t]=tot:0;
son[tot][0]=son[tot][1]=0,S[pii(l,r)]=tot;
siz[tot]=1,sum[tot]=(R[tot]=r)-(L[tot]=l)+1;
return tot;
}
inline void rotate(int x){
int y=fa[x],z=fa[y],t=which(x);
if(z)son[z][which(y)]=x;
fa[x]=z,fa[y]=x,son[y][t]=son[x][t^1],son[x][t^1]=y;
if(son[y][t])fa[son[y][t]]=y;
pushup(y),pushup(x);
}
inline void splay(int x,int ff=0){
while(fa[x]!=ff){
if(fa[fa[x]]!=ff)rotate(which(x)==which(fa[x])?fa[x]:x);
rotate(x);
}
if(!ff)rt=x;
}
inline void insert(int l,int r,int k){
--k;
int p=rt,ft=0,t;
while(p){
ft=p;
if(siz[lc]>=k)p=lc,t=0;
else k-=siz[lc]+1,p=rc,t=1;
}
splay(build(l,r,ft,t));
}
inline int pre(int p){
splay(p),p=lc;
while(rc)p=rc;
return splay(p),p;
}
inline int suf(int p){
splay(p),p=rc;
while(lc)p=lc;
return splay(p),p;
}
inline void delet(int p){
int pr=pre(p),su=suf(p);
splay(pr),splay(su,pr),son[su][0]=0,splay(su);
}
inline void init(){
insert(0,0,1),insert(1,n,2),insert(n+1,n+1,3);
upd.insert(0),upd.insert(n+1);
}
inline int update(int x,int y){
int l,r,t=mp[x]?mp[x]:x,p,ret;
mp[y]=mp[x]?mp[x]:x,imp[mp[y]]=y,mp.erase(x);
It ir=upd.lower_bound(t),il;
if(*ir==t)splay(p=S[pii(t,t)]),ret=sum[lc];
else{
il=ir;
while(*ir<t)++ir;
while(*il>t)--il;
l=*il+1,r=*ir-1;
splay(p=S[pii(l,r)]),ret=sum[lc]+t-l;
}
return ret;
}
inline int Pre(int x){
int l,r,t=mp[x]?mp[x]:x,p,ret,rk;
It ir=upd.lower_bound(t),il;
if(*ir==t){
splay(p=S[pii(t,t)]),ret=sum[lc];
delet(p),insert(t,t,2);
}
else{
il=ir;
while(*ir<t)++ir;
while(*il>t)--il;
l=*il+1,r=*ir-1,splay(p=S[pii(l,r)]),ret=sum[lc]+t-l,rk=siz[lc]+1;
upd.insert(t);
delet(p);
if(t==l)insert(t+1,r,rk);
else if(t==r)insert(l,t-1,rk);
else insert(l,t-1,rk),insert(t+1,r,rk+1);
insert(t,t,2);
}
return ret;
}
inline int Suf(int x){
int l,r,t=mp[x]?mp[x]:x,p,ret,rk;
It ir=upd.lower_bound(t),il;
if(*ir==t){
splay(p=S[pii(t,t)]),ret=sum[lc];
delet(p),insert(t,t,siz[rt]);
}
else{
il=ir;
while(*ir<t)++ir;
while(*il>t)--il;
l=*il+1,r=*ir-1,splay(p=S[pii(l,r)]),ret=sum[lc]+t-l,rk=siz[lc]+1;
upd.insert(t);
delet(p);
if(t==l)insert(t+1,r,rk);
else if(t==r)insert(l,t-1,rk);
else insert(l,t-1,rk),insert(t+1,r,rk+1);
insert(t,t,siz[rt]);
}
return ret;
}
inline int Rank(int k){
++k;
int p=rt,ret;
while(p){
if(sum[lc]>=k)p=lc;
else if(sum[lc]+R[p]-L[p]+1>=k){
ret=L[p]+(k-sum[lc])-1;
break;
}
else k-=sum[lc]+R[p]-L[p]+1,p=rc;
}
return !imp[ret]?ret:imp[ret];
}
#undef lc
#undef rc
}
int main(){
n=read(),m=read();
Splay::init();
for(ri x,y,lastans=0,op;m;--m,++tt){
op=read();
switch(op){
case 1:{x=read()-lastans,y=read()-lastans,lastans=Splay::update(x,y);break;}
case 2:{x=read()-lastans,lastans=Splay::Pre(x);break;}
case 3:{x=read()-lastans,lastans=Splay::Suf(x);break;}
case 4:{x=read()-lastans,lastans=Splay::Rank(x);break;}
}
cout<<lastans<<'\n';
}
return 0;
}
2019.03.28 bzoj3595: [Scoi2014]方伯伯的Oj(splay+map+set)的更多相关文章
- 2019.03.28 bzoj3597: [Scoi2014]方伯伯运椰子(01分数规划)
传送门 题意咕咕咕有点麻烦不想写 思路: 考虑加了多少一定要压缩多少,这样可以改造边. 于是可以通过分数规划+spfaspfaspfa解决. 代码: #include<bits/stdc++.h ...
- 2019.03.28 bzoj3594: [Scoi2014]方伯伯的玉米田(二维bit优化dp)
传送门 题意咕咕咕 思路:直接上二维bitbitbit优化dpdpdp即可. 代码: #include<bits/stdc++.h> #define N 10005 #define K 5 ...
- 2019.03.28 bzoj3598: [Scoi2014]方伯伯的商场之旅(带权中位数+数位dp)
传送门 题意咕咕咕自己读吧挺简单的 思路: 由带权中位数的性质可以得到对于每个数放在每个二进制位的代价一定是个单调或者单峰函数,因此我们先把所有的数都挪到第一个位置,然后依次向右枚举峰点(极值点)把能 ...
- luogu P3285 [SCOI2014]方伯伯的OJ splay 线段树
LINK:方伯伯的OJ 一道稍有质量的线段树题目.不写LCT splay这辈子是不会单独写的 真的! 喜闻乐见的是 题目迷惑选手 \(op==1\) 查改用户在序列中的位置 题目压根没说位置啊 只有排 ...
- BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常
Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-”,一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和 ...
- [BZOJ3595][SCOI2014]方伯伯的OJ(裂点Splay)
用一棵Splay按名次维护每个点,其中一个节点对应初始编号连续的一段区间,这样总节点数是$O(m)$的. 对每个编号记录这个点被Splay的那个节点维护,用std::map存储,只记录被修改的点. 每 ...
- BZOJ3595 : [Scoi2014]方伯伯的Oj
由于n很大,有2e8,所以不能直接用splay来维护排名 把splay修改一下 每个节点维护一个区间[l,r],表示编号在[l,r]之间的所有点都在这里 需要支持一个takeout操作: 把编号为k的 ...
- 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\) 个用户 ...
随机推荐
- SpringMVC中的一些注解
@Controller:表明该类是一个Controller: @RequestMapping(参数) :为类或者方法定义一个url @RequestParam(value = "id&quo ...
- WPF网格绑定控件并控制控件是否可读
<DataGridTemplateColumn Width="100" Header="实测值"> <DataGridTemplateColu ...
- python跨平台注释
使python程序运行在window以外的平台上 !# user/bin/python
- Vue-input框checkbox强制刷新
在引用input框的checkbox属性时,选中后会出现数据已经刷新,checkbox选中状态不会改变.这时在事件触发后可以调用this.$forceUpdate(),强制刷新页面解决这个问题. in ...
- asp.net 下载视频 保存视屏
第一张图片为html,第一站图片为js上传视频并播放,限定大小,第三张图片是将视频保存到以字节流的方式保存到数据中,或者是将视频保存到项目中 String filename=this.Filevide ...
- leedcode算法解题思路
1.两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个 ...
- opencv关于Mat类中的Scalar()---颜色赋值
这个 CvScalar就是一个可以用来存放4个double数值的数组(O'Reilly的书上写的是4个整型成员):一般用来存放像素值(不一定是灰度值哦)的,最多可以存放4个通道的. typedef s ...
- 数据如何输入输出_Spark
1)输入:在Spark程序运行中,数据从外部数据空间(如分布式存储:textFile读取HDFS等,parallelize方法输入Scala集合或数据)输入Spark,数据进入Spark运行时数据空间 ...
- Javaweb过滤器
http://blog.csdn.net/reggergdsg/article/details/52821502
- web安全之机器学习入门——3.2 决策树与随机森林
目录 简介 决策树简单用法 决策树检测P0P3爆破 决策树检测FTP爆破 随机森林检测FTP爆破 简介 决策树和随机森林算法是最常见的分类算法: 决策树,判断的逻辑很多时候和人的思维非常接近. 随机森 ...