stm带裂点splay 列队

Posted 20020723yjx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm带裂点splay 列队相关的知识,希望对你有一定的参考价值。

重构了一天的代码,,,

dalao过来10min帮我A了2333  Orz  Orz  Orz

维护n+1颗splay,分别代表n行,前1~m-1个,最后1棵表示最后1列

每个节点表示人的编号为[l,r)。(因为有些人一直挨在一起,所以可以合并)

裂点细节比较多。

还有,每行只可能插入最后一个位置(即这一行有人走了,插入第m-1个位置),所以找对应这棵splay最大的位置,把最后一行对应点弹出,作为这个最大位置的右儿子即可(中序遍历它就在最后了)。

代码,,,可读性还算可以吧,,

#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<vector>
#include<iostream>
#define ll long long
#define re register
#define inf 0x7f7f7f7f
#define inl inline
#define sqr(x) (x*x)
//#define eps 1e-8
#define debug printf("debug
");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
using namespace std;
//const ll mod;
const ll MAXN=3e5+10;
inl ll read() {
    re ll x = 0; re int f = 1;
    char ch = getchar();
    while(ch<0||ch>9) { if(ch== - ) f = -1; ch = getchar(); }
    while(ch>=0&&ch<=9) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x * f;
}
inl char readc() {
    char ch=getchar();
    while((z<ch||ch<a)&&(Z<ch||ch<A)) ch=getchar();
    return ch;
}
inl void write(re ll x){
    if(x>=10)write(x/10);
    putchar(x%10+0);
}
inl void writeln(re ll x){
    if(x<0) {x=-x;putchar(-);}
    write(x); puts("");
}
inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
inl ll Lcm(re ll a,re ll b) {return a/gcd(a,b)*b;}
inl void FR() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}
inl void FC() {
    fclose(stdin);
    fclose(stdout);
}
ll Tcnt;
struct Node {
    ll fa,son[2],l,r,siz;
}nod[MAXN*10];
struct Splay {
    ll rt;
    inl ll newnod(ll l,ll r) {
        ++Tcnt;
        nod[Tcnt].fa=nod[Tcnt].son[0]=nod[Tcnt].son[1]=0;
        nod[Tcnt].siz=(nod[Tcnt].r=r)-(nod[Tcnt].l=l);
        return Tcnt;
    }
    inl void init(ll l,ll r) {rt=newnod(l,r);}
    inl void pushup(ll x) {
        nod[x].siz=nod[x].r-nod[x].l+nod[nod[x].son[1]].siz+nod[nod[x].son[0]].siz;
    }
    inl ll dir(ll x) {return nod[nod[x].fa].son[1]==x;}
    inl void rotate(ll x) {
        ll y = nod[x].fa, z = nod[y].fa,o=dir(x);
        nod[x].fa = z;
        if(y==rt) rt=x;
        else nod[z].son[dir(y)] = x;
        if(nod[y].son[o]=nod[x].son[o^1]) nod[nod[y].son[o]].fa=y;
        nod[nod[x].son[o^1]=y].fa=x;
        pushup(y);pushup(x);
    }
    inl void splay(ll x){
        for(ll y;y=nod[x].fa;rotate(x)){
            if(nod[y].fa) rotate(dir(x)==dir(y)?y:x);
        }
    }
    inl ll splitnod(ll x,ll k) {
        k+=nod[x].l;
        ll y=newnod(k,nod[x].r);
        nod[x].r=k;
        if(!nod[x].son[1]) {nod[nod[x].son[1]=y].fa=x;}
        else {
            ll t=nod[x].son[1];
            while(nod[t].son[0]) t=nod[t].son[0];
            nod[nod[t].son[0]=y].fa=t;
            while(t!=x) pushup(t),t=nod[t].fa;
        }
        splay(y);
        return y;
    }
    ll popk(ll k) {
        ll o=rt;
        while(1) {
            if(nod[nod[o].son[0]].siz>=k) {o=nod[o].son[0];}
            else {
                k-=nod[nod[o].son[0]].siz;
                if(k<=nod[o].r-nod[o].l) {
                    if(k!=nod[o].r-nod[o].l) splitnod(o,k);
                    if(k!=1) o=splitnod(o,k-1);
                    break ;
                }
                else {
                    k-=nod[o].r-nod[o].l;
                    o=nod[o].son[1];
                }
            }
        }
        splay(o);
        nod[nod[o].son[0]].fa=nod[nod[o].son[1]].fa=0;
        if(!nod[o].son[0]) {rt=nod[o].son[1];}
        else {
            ll t=nod[o].son[0];
            while(nod[t].son[1]) t=nod[t].son[1];
            splay(t);
            pushup(rt=nod[nod[t].son[1]=nod[o].son[1]].fa=t);
        }
        return nod[o].l;
    }
    inl void insert(ll x) {
        ll y=newnod(x,x+1);
        if(!rt) rt=y;
        else {
            ll o=rt;
            while(nod[o].son[1]) o=nod[o].son[1];
            splay(o);
            pushup(nod[nod[o].son[1]=y].fa=o);
        }
    }
}s[MAXN];
ll n,m,q;
int main() {
//  FR();
    Tcnt=0;
    n=read(),m=read(),q=read();
    for(re ll i=1;i<=n;i++) s[i].init((i-1)*m+1,i*m);
    s[0].init(m,m+1);
    for(re ll i=2;i<=n;i++) s[0].insert(i*m);
    ll p;
    for(re ll i=1;i<=q;i++) {
        re ll x=read(),y=read();
        s[x].insert(s[0].popk(x));
        writeln(p=s[x].popk(y));
        s[0].insert(p);
    }
//  FC();
    return 0;
}

 

以上是关于stm带裂点splay 列队的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2017列队(phalanx)解题报告

学术篇NOIP2017 d2t3 列队phalanx splay做法

[NOIP2017D2T3]列队

[luoguP3960] 列队(动态开点线段树)

[LuoguP2161[ [SHOI2009]会场预约 (splay)

Codevs1034家园(最大流,裂点)