传送门

题意简述:

给一个有优先级的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. 项目集成swagger【转载】

    地址链接:https://blog.csdn.net/lx1309244704/article/details/81808788 swagger是一款高效易用的嵌入式文档插件,同时支持在线测试接口,快 ...

  2. CSS 背景图像 重复图像

    重复图像 background-repeat 属性可以重复图像,这对于小图片来说是福音. background-repeat 属性有6个值: repeat 背景图像在垂直方向和水平方向都重复 repe ...

  3. Java Script 简介

    Java Script 简介 JavaScript 是世界上最流行的编程语言. 这门语言可用于 HTML 和 web,更可广泛用于服务器.PC.笔记本电脑.平板电脑和智能手机等设备.JavaScrip ...

  4. java 安装教程

    https://www.cnblogs.com/xuyangblog/p/5455381.html

  5. ES match match_phrase term willcard的查询原理

    比如:要求实现SQL中like “%xxxx%”的匹配效果. wildcard通配 这种效果在ES中最匹配的做法是用wildcard query通配,这种情况不会对query分词,而是直接遍历倒排索引 ...

  6. mysql常用的统计类sql ,以及批量循环插入数据

    今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ...

  7. HashMap、Hashtable、ConcurrentHashMap的原理与区别(简述)

    HashTable 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相 ...

  8. synchronized锁机制 之 代码块锁(转)

    synchronized同步代码块 用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个较长时间的任务,那么B线程必须等待比较长的时间.这种情况下可以尝试使用 ...

  9. 按enter 导致整个页面刷新的解决办法

    1.如果用的又from表单的存在,则在form中添加事件 <form onsubmit="return false;">.......</form> 2.增 ...

  10. Centos7 安装可视化图形

    因为安装的Centos7最小安装包,虚拟机没有可视化界面,可以采用下列命令,安装可视化界面. init id::initdefault: yum install -y libdevmapper* yu ...