传送门

题意简述:

给一个有优先级的nnn个人的序列,初始的时候第iii个人排名为iii,现在有mmm个操作,种类如下:

  1. 把编号为xxx的改成yyy,输出改前xxx的排名
  2. 把编号为xxx放到队首,输出改前xxx的排名
  3. 把编号为xxx放到队尾,输出改前xxx的排名
  4. 输出排名为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)的更多相关文章

  1. 2019.03.28 bzoj3597: [Scoi2014]方伯伯运椰子(01分数规划)

    传送门 题意咕咕咕有点麻烦不想写 思路: 考虑加了多少一定要压缩多少,这样可以改造边. 于是可以通过分数规划+spfaspfaspfa解决. 代码: #include<bits/stdc++.h ...

  2. 2019.03.28 bzoj3594: [Scoi2014]方伯伯的玉米田(二维bit优化dp)

    传送门 题意咕咕咕 思路:直接上二维bitbitbit优化dpdpdp即可. 代码: #include<bits/stdc++.h> #define N 10005 #define K 5 ...

  3. 2019.03.28 bzoj3598: [Scoi2014]方伯伯的商场之旅(带权中位数+数位dp)

    传送门 题意咕咕咕自己读吧挺简单的 思路: 由带权中位数的性质可以得到对于每个数放在每个二进制位的代价一定是个单调或者单峰函数,因此我们先把所有的数都挪到第一个位置,然后依次向右枚举峰点(极值点)把能 ...

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

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

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

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

  6. [BZOJ3595][SCOI2014]方伯伯的OJ(裂点Splay)

    用一棵Splay按名次维护每个点,其中一个节点对应初始编号连续的一段区间,这样总节点数是$O(m)$的. 对每个编号记录这个点被Splay的那个节点维护,用std::map存储,只记录被修改的点. 每 ...

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

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

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

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

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

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

随机推荐

  1. Prometheus

    官方网址:https://prometheus.io/ GitHub网址:https://github.com/prometheus/prometheus 软件下载地址:https://prometh ...

  2. 2017-11-11 Sa Oct Spider

    2017-11-11 Sa Oct Spider 4:33 PM Again. Firstly test liburl: # -*- coding: utf-8 -*- import json imp ...

  3. 一些常用的 std 类型

    [std::allocator] 标准库中包含一个名为allocator的类,允许我们将分配和初始化分离.使用allocator通常会提供更好的性能和更灵活的内存管理能力. 标准库allocator类 ...

  4. day50 盒子显隐2D形变

    复习 1.浮动布局 解决block盒子同行显示 => 不完全脱离文档流 => 不再撑开父级高度 脱离文档流: 不在页面中占位(显示层次高于文档流) 不完全: 可以通过清浮动操作, 让子级重 ...

  5. C#使用Owin技术部署轻量级webApi服务

    写在前面: 除了使用IIS可以启用WebApi之外,微软还提供了Owin技术,免除了IIS繁琐的部署配置,只需要运行编写好的程序,即可启用webApi服务,是不是很爽呢? 对于Owin技术的详细介绍这 ...

  6. CentOS7 安装并配置MySQL8.0

    安装环境 linux版本:CentOS 7.6 x64 Mysql:8.0 在CentOS中默认安装有MariaDB,但是我们需要的是MySQL,安装MySQL可以覆盖MariaDB. MariaDB ...

  7. canvas 的HTML属性

    (一) width/height 默认值与单位 Canvas  标签只有两个属性—— width\height,作为一种替换元素,它默认大小为300×150像素. canvas的单位只能是是px,值只 ...

  8. oralce 的安装以及plsql的配置的html连接

    https://www.cnblogs.com/xkstudy/p/6400738.html

  9. 对象属性拷贝工具类大全==>Bean的属性拷贝从此不用愁

    大家在做java开发时,肯定会遇到api层参数对象传递给服务层,或者把service层的对象传递给dao层,他们之间又不是同一个类型对象,但字段又是一样,如果还是用普通的get.set方式来处理话,比 ...

  10. 【CSS】Sticky Footer 布局

    什么是 Sticky Footer 布局? Sticky Footer 布局是一种将 footer 吸附在底部的CSS布局. footer 可以是任意的元素,该布局会形成一种当内容不足,footer ...