传送门

题意简述:

给一个有优先级的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. 移动端ios下H5的:active样式失效的解决方法

    在body上绑定一个touchstart事件,空函数就行: document.body.addEventListener('touchstart', function(){}, false) 或者在b ...

  2. [转] ESXI6.5 误将硬盘阵列卡配置为passthru直通模式后, 找不到硬盘的问题

    There is no easy way to do it, it seems. So I wanted to say that I couldn't afford to do an upgrade ...

  3. select简单循环嵌套

    访问学生的物理最高成绩,并且打印出来,单个要打印出所有的信息 在添加几个 and 就可以啦. select  student.gender,student.sname from student whe ...

  4. Spring:Ioc和DI

    一.摘要         本文为作者搜集的Spring关于IoC/DI相关知识的记录整理笔记.介绍了IoC(控制反转)是一种设计原则,用于降低代码的耦合度.介绍了IoC是通过BeanDefinitio ...

  5. java第四章接口

    接口(interface) 语法:修饰符 interface 接口名 extends 父接口1,父接口2....{ //常量定义   //方法定义} class 类名 extends 父类名 impl ...

  6. jira7.3.6 linux安装

    一.环境准备 jira7.3的运行是依赖java环境的,也就是说需要安装jdk并且要是1.8以上版本,如下: http://www.oracle.com/technetwork/java/javase ...

  7. [Spring实战笔记]4面向切面编程的Spring-代理

    代理 代理(Proxy)是一种设计模式,可以在目标对象实现的基础上,扩展目标对象的功能. 代理对象是对目标对象的扩展,并会调用目标对象. 三种代理模式 静态代理 100% 代理对象与目标对象要实现相同 ...

  8. WPF中textBlock 变色功能

    <Window.Resources> <Storyboard x:Key="OnLoaded" RepeatBehavior="Forever" ...

  9. 实用矩阵类(Matrix)(带测试)

    引言: 无意间看到国外一个网站写的Matrix类,实现了加减乘除基本运算以及各自的const版本等等,功能还算比较完善,,于是记录下来,以备后用: #ifndef MATRIX_H #define M ...

  10. oracle 中查看数据库表中某个字段是否重复

    1.select  表中重复的字段 from  表名 group by 表中的重复的字段 HAVING count(表中的重复的字段)>1 举例说明 : 表名 : psp_cell_model  ...