【3595: [Scoi2014]方伯伯的Oj】区间拆分splay

少有的一遍写完过完样例就A的题,本身并不难,但这道题的思想还是很有用的。 BZOJ3595

3595: [Scoi2014]方伯伯的Oj

Time Limit: 6 Sec  Memory Limit: 256 MB Submit: 772  Solved: 306 [Submit][Status][Discuss]

Description

方伯伯正在做他的Oj。现在他在处理Oj上的用户排名问题。 Oj上注册了n个用户,编号为1~”,一开始他们按照编号排名。方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为1 x y,意味着将编号为z的用户编号改为V,而排名不变,执行完该操作后需要输出该用户在队列中的位置,数据保证x必然出现在队列中,同时1,是一个当前不在排名中的编号。 2.操作格式为2 x,意味着将编号为x的用户的排名提升到第一位,执行完该操作后需要输出执行该操作前编号为z用户的排名。 3.操作格式为3 x,意味着将编号为z的用户的排名降到最后一位,执行完该操作后需要输出执行该操作前编号为z用户的排名。 4.操作格式为4 k,意味着查询当前排名为足的用户编号,执行完该操作后需要输出当前操作用户的编号。 但同时为了防止别人监听自己的工作,方伯伯对他的操作进行了加密,即将四种操作的格式分别改为了: 1 x+a y+a 2 x+a 3 x+a 4 k+a 其中a为上一次操作得到的输出,一开始a=0。 例如: 上一次操作得到的输出是5 这一次操作的输入为:1  13 15 因为这个输入是经过加密后的,所以你应该处理的操作是1 8 10 现在你截获丁方伯伯的所有操作,希望你能给出结果。

Input

输入的第1行包含2个用空格分隔的整数n和m,表示初始用户数和操作数。 此后有m行,每行是一个询问,询问格式如上所示。

Output

输出包含m行。每行包含一个整数,其中第i行的整数表示第i个操作的输出。

Sample Input

10 10 1 2 11 3 13 25 37 28 2 10 2 11 3 14 2 18 4 9

Sample Output

2 2 2 4 3 5 5 7 8 11

HINT

对于 100% 的数据,1 ≤ n ≤ 10^8,1 ≤ m ≤ 10^5
输入保证对于所有的操作 1,2,3,x 必然已经出现在队列中,同时对于所有操作 1,1 ≤ y ≤ 2 × 10^8,并且
y 没有出现在队列中。
对于所有操作 4,保证 1 ≤ k ≤ n。
乍眼看,splay板题?
欸不对怎么n这么大?
其实我们完全splay维护一个区间,记录L,R。同时我们利用两个map互相映射方便我们操作,之后初始一个splay结点囊括[1,n],之后只要从中间分裂,如[1,x-1][x][x+1,n]这样就可以了(当然具体怎样要细加分析)。
贼丑的code
#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#define zig(x) zigzag(x,1)
#define zag(x) zigzag(x,2)
using namespace std;
const int maxn = 500005;
int n,m;
map<int,int>ma1; // origin id --> splay id (Ldd)
map<int,int>ma2; // splay id --> origin id 
int ls[maxn],rs[maxn],fa[maxn],siz[maxn],L[maxn],R[maxn],rt,tot;
void upd(int x) {
    siz[x] = siz[ls[x]] + siz[rs[x]] + R[x] - L[x] + 1;
}
void zigzag(int x,int kd) {
    int y,z;
    y = fa[x]; z = fa[y];
    if(z) {
        if(ls[z]==y) ls[z] = x;
        else rs[z] = x;
    }
    fa[x] = z; fa[y] = x;
    if(kd==1) {
        ls[y] = rs[x];
        fa[ls[y]] = y;
        rs[x] = y;
    } else{
        rs[y] = ls[x];
        fa[rs[y]] = y;
        ls[x] = y;
    }
    upd(y); upd(x);
}
void splay(int x){
    int y , z;
    while(fa[x]) {
        y = fa[x]; z = fa[y];
        if(!z) {
            if(ls[y]==x) zig(x);
            else zag(x);
        } else {
            if(ls[z]==y) {
                if(ls[y]==x) zig(y),zig(x);
                else zag(x),zig(x);
            }else {
                if(rs[y]==x) zag(y),zag(x);
                else zig(x),zag(x);
            }
        }
    }
    rt = x;
}
int split(int spb,int x) {
    splay(spb);
    if(x==L[spb]) {
        ++tot; 
        ls[tot] = ls[spb];
        ls[spb] = tot; 
        fa[ls[tot]] = tot;
        fa[tot] = spb;
        L[spb]++;
        L[tot] = R[tot] = x;
        ma1[x] = tot;
        ma2[tot] = x;
        ma1[x+1] = spb;
        ma2[spb] = x+1; 
        upd(tot); upd(spb);
        return tot;
    } else if(x==R[spb]) {
        ++tot;
        rs[tot] = rs[spb];
        rs[spb] = tot;
        fa[rs[tot]] = tot;
        fa[tot] = spb;
        R[spb]--;
        R[tot] = L[tot] = x;
        ma1[x] = tot;
        ma2[tot] = x;
        ma1[L[spb]] = spb;
        ma2[spb] = L[spb];
        upd(tot); upd(spb);
        return tot;
    }
    int lo = ++tot;
        ls[lo] = ls[spb];
        ls[spb] = lo;
        fa[lo] = spb; 
        fa[ls[lo]] = lo;
        L[lo] = L[spb];
        L[spb] = x;
        R[lo] = x-1;
        ma1[L[lo]] = lo;
        ma2[lo] = L[lo];
        ma1[x] = spb;
        ma2[spb] = x;
    int ro = ++tot;
        rs[ro] = rs[spb];
        rs[spb] = ro;
        fa[ro] = spb;
        fa[rs[ro]] = ro;
        R[ro] = R[spb];
        R[spb] = x;
        L[ro] = x+1;

        ma1[L[ro]] = ro;
        ma2[ro] = L[ro];

        upd(lo); upd(ro); upd(spb);
    return spb;
}
int ggg(int x){
    map<int,int>::iterator it;
    it = ma1.upper_bound(x);
    it--;
    int spb = it->second;
    if(R[spb]==L[spb]) return spb;
    else return split(spb,x);
}
int getmax(int x) {
    while(rs[x]) x = rs[x];
    return x;
}
int getk(int k) {
    int p = rt;
    while(p) {
        if( siz[ls[p]] + 1 <= k && k <= siz[ls[p]] + (R[p]-L[p]+1) ) break;
        else {
            if(siz[ls[p]]>=k) p = ls[p];
            else {
                k -= siz[ls[p]] + (R[p]-L[p]+1);
                p = rs[p];
            }
        }
    }
    return p;
}
void insfi(int x) {
    int p = rt;
    while(p) {
        siz[p] += (R[x]-L[x]+1);
        if(ls[p]) p = ls[p];
        else {
            ls[p] = x;
            fa[x] = p;
            upd(p);
            break;
        }
    }
    splay(x);
}
void insla(int x) {
    int p = rt;
    while(p) {
        siz[p] += (R[x]-L[x]+1);
        if(rs[p]) p = rs[p];
        else {
            rs[p] = x;
            fa[x] = p;
            upd(p);
            break;
        }
    }
    splay(x);
}
void cut(int p) {
    splay(p);
    int lo = ls[p]; int ro = rs[p];
    fa[lo] = fa[ro] = ls[p] = rs[p] = 0;
    upd(p);
    if(!lo) {
        rt = ro; return;
    }
    lo = getmax(lo);
    splay(lo);
    fa[ro] = lo; rs[lo] = ro;
    upd(lo);
    return;
}
int main() {
    scanf("%d%d",&n,&m);
    rt = ++tot; L[tot] = 1; R[tot] = n;
    ma1[1] = 1; ma2[1] = 1;
    siz[tot] = n;
    int lastans = 0; 
    for(int i=1;i<=m;i++) {
        int op; scanf("%d",&op);
        if(op==1) {
            int x,y; scanf("%d%d",&x,&y);
            x -= lastans; y -= lastans;
            int spb = ggg(x);
            ma1[x] = 0;
            ma2[spb] = y;
            ma1[y] = spb;
            splay(spb);
            lastans = siz[ls[spb]] + 1;
            printf("%d\n",lastans);
        } else if(op==2) {
            int x; scanf("%d",&x);
            x -= lastans;
            int spb = ggg(x);
            splay(spb);
            lastans = siz[ls[spb]] + 1;
            printf("%d\n",lastans);
            cut(spb);
            insfi(spb);
        } else if(op==3) {
            int x; scanf("%d",&x);
            x -= lastans;
            int spb = ggg(x);
            splay(spb);
            lastans = siz[ls[spb]] + 1;
            printf("%d\n",lastans);
            cut(spb);
            insla(spb);
        }else {
            int k; scanf("%d",&k);
            k -= lastans;
            int spb = getk(k);
            splay(spb);
            k-=siz[ls[spb]];
            lastans = ma2[spb]+ k - 1;
            printf("%d\n",lastans);
        }
    }
}
 
posted @ 2018-11-23 00:31  Newuser233  阅读(9)  评论(0)    收藏  举报