码迷,mamicode.com
首页 > 其他好文 > 详细

【NOIP2017】列队(Splay)

时间:2018-03-31 21:33:46      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:printf   维护   cpp   set   noip   amp   class   一个   reg   

【NOIP2017】列队(Splay)

题面

洛谷

题解

其实好简单啊。。。
对于每一行维护一棵\(Splay\)
对于最后一列维护一棵\(Splay\)
\(Splay\)上一个节点表示一段区间
每次出去一个人就是把当前的\(Splay\)的一个节点拆分成\(3\)

然后就很简单了。。
细节比较多。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2000000
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Node
{
    int ch[2],ff;
    ll size;
    ll l,r;
}t[MAX];
int tot;
int n,m,Q;
struct SplayTree
{
    int root;
    int Node(ll l,ll r){++tot;t[tot].l=l;t[tot].r=r;t[tot].size=r-l;return tot;}
    void pushup(int x){t[x].size=t[ls].size+t[rs].size+t[x].r-t[x].l;}
    void rotate(int x)
    {
        int y=t[x].ff,z=t[y].ff;
        int k=t[y].ch[1]==x;
        if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
        t[y].ch[k]=t[x].ch[k^1];if(t[x].ch[k^1])t[t[x].ch[k^1]].ff=y;
        t[x].ch[k^1]=y;t[y].ff=x;
        pushup(y);pushup(x);
    }
    void Splay(int x)
    {
        for(int y=t[x].ff;y;rotate(x),y=t[x].ff)
            if(t[y].ff)(rand()&1)?rotate(x):rotate(y);
        root=x;
    }
    int Split(int x,ll K)
    {
        K+=t[x].l;
        int y=Node(K,t[x].r);t[x].r=K;
        if(!rs)t[y].ff=x,rs=y;
        else
        {
            int u=rs;
            while(t[u].ch[0])u=t[u].ch[0];
            t[y].ff=u;t[u].ch[0]=y;
        }
        Splay(y);return y;
    }
    ll DelKth(ll K)
    {
        int x=root;
        while(2333)
        {
            if(K<=t[ls].size)x=ls;
            else
            {
                K-=t[ls].size;
                if(K<=t[x].r-t[x].l)
                {
                    if(K<t[x].r-t[x].l)Split(x,K);
                    if(K>1)x=Split(x,K-1);
                    break;
                }
                else K-=t[x].r-t[x].l,x=rs;
            }
        }
        Splay(x);t[ls].ff=t[rs].ff=0;
        if(!ls)root=rs;
        else
        {
            int y=ls;
            while(t[y].ch[1])y=t[y].ch[1];
            Splay(y);
            root=t[t[y].ch[1]=t[x].ch[1]].ff=y;
            pushup(y);
        }
        return t[x].l;
    }
    void Insert(ll k)
    {
        int y=Node(k,k+1);
        if(!root)root=y;
        else
        {
            int x=root;
            while(rs)x=rs;
            Splay(x);
            t[rs=y].ff=x;pushup(x);
        }
    }
}Splay[MAX];
int main()
{
    n=read();m=read();Q=read();
    for(int i=1;i<=n;++i)Splay[i].root=Splay[i].Node(1ll*i*m-m+1,1ll*i*m);
    for(int i=1;i<=n;++i)Splay[0].Insert(1ll*i*m);
    while(Q--)
    {
        int x=read(),y=read();ll ans;
        Splay[x].Insert(Splay[0].DelKth(x));
        printf("%lld\n",ans=Splay[x].DelKth(y));
        Splay[0].Insert(ans);
    }
    return 0;
}

【NOIP2017】列队(Splay)

标签:printf   维护   cpp   set   noip   amp   class   一个   reg   

原文地址:https://www.cnblogs.com/cjyyb/p/8684116.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!