传送门

题意简述:

给一个有优先级的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. ElasticSearch 2.X升级到6.X遇到的几个问题

    1.IndexExists检测索引是否存在,更简洁了,可以这样 _ElasticClient.IndexExists(indices : indexName).Exists 2.索引数据的时候,如果数 ...

  2. hadoop常见问题

    Q1.什么是 Hadoop? Hadoop 是一个开源软件框架,用于存储大量数据,并发处理/查询在具有多个商用硬件(即低成本硬件)节点的集群上的那些数据.总之,Hadoop 包括以下内容: HDFS( ...

  3. java中常规使用的mysql语句

    1.登录型校验 limit 1,例如: SELECT `password`FROM workerWHERE phone = 18611406603LIMIT 1 结果无值,不需验证;有值,校验 2.存 ...

  4. IDEA 中tomcat日志位置

    参考 https://blog.csdn.net/dela_/article/details/78555977 /home/dela/.IntelliJIdea2017.1/system/tomcat ...

  5. iframe登录超时跳转登录页面

    1.可以在登录页面加jQuery验证 $(function () { //判断一下当前是不是做顶层,如果不是,则做一下顶层页面重定向 if (window != top) { top.location ...

  6. django filter or 多条件查询

    功能:django中实现多条件查询 或关系: from django.db.models import Q return qs.filter(Q(notice_to_group__contains=' ...

  7. 编辑输出“Hello World”

    一.新建java项目 执行“文件->新建->项目建立”,打开建立新项目对话框,在编辑框中输入项目名,其他选项为默认值,随后点击“完成”按钮. 二.新建java类 执行“文件->新建- ...

  8. echarts 图表重新加载,原来的数据依然存在图表上

    问题 在做一个全国地图上一些饼图,并且向省一级的地图钻取的时候,原来的饼图依然显示 原因 echars所有添加的图表都在一个series属性集合中,并且同一个echars对象默认是合并之前的数据的,所 ...

  9. 谈谈逆向android里面的so

    1. 加密sgf算法分析 2.gnugo瘦身记

  10. 一个不错的多叉树, stl风格

    tree<std::string> tr9; tree<std::string>::pre_order_iterator iter1; tr9.set_head("h ...