zoukankan      html  css  js  c++  java
  • NOIP2017 列队

    NOIP2017 列队

    这题看上去 fhq_Treap 一脸可做

    看完 ** 的数据范围就不可做了

    毕竟 d2t3 ,得有点骚操作的

    我们发现操作次数并不多

    可以试着“动态开点”

    就是用到这个位置的时候再给它开辟一个节点

    不用就和其他不用的连为一体作为一个节点就好了

    挺麻烦不过代码并不长

    核心部分代码:

    pair<int, int> Split(int cur, ll k) {
        if(!cur || !k) return make_pair(0, cur);
        pair<int, int> res;
        if(t[lson].siz >= k) {
            res = Split(lson, k);
            lson = res.second;
            pushup(cur);
            res.second = cur;
        } else if(t[lson].siz + t[cur].len() >= k) {
            register ll l = t[cur].l, r = t[cur].r;
            int newrt;
            k -= t[lson].siz;
            t[cur].rerange(l, l + k - 1ll);
            newrt = newnode(l + k, r);
            res.second = Merge(newrt, rson);
            rson = 0;
            if(t[cur].len() <= 0) cur = lson;
            pushup(cur);
            res.first = cur;
        } else {
        	res = Split(rson, k - t[lson].siz - t[cur].len());
            rson = res.first;
            pushup(cur);
            res.first = cur;
        }
        return res;
    }
    

     意思就是说, 如果当前的区间是我想要操作的区间(要 Split 的区间),我就给它多开另一个节点,让他们两个作为裂开后的左右两部分

    根据 fhq_Treap 的经典 Split 操作的过程,我们不难写出上面代码的细节

    需要额外注意的就是在 newnode 的时候需要把节点的 size 搞一下


    完整代码:

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    #include<ctime>
    #define lson t[cur].ch[0]
    #define rson t[cur].ch[1]
    using namespace std;
    
    typedef long long ll;
    const int MAXN = 300005;
    
    struct Node{
        ll siz, l, r;
        int ch[2], prio;
        Node() {ch[0] = ch[1] = 0; siz = l = r = 0ll;}
        inline void clear() {
            ch[0] = ch[1] = prio = 0;
            siz = l = r = 0ll;
            return;
        }
        inline void rerange(ll x, ll y) {
        	l = x;
        	r = y;
        	return;
        }
        inline ll len() {
            return r - l + 1ll;
        }
    }t[MAXN * 16];
    int n, m, q, poolcur;
    ll Root[MAXN];
    
    inline int newnode(ll l, ll r) {
        if(l > r) return 0;
        register int cur = ++poolcur;
        t[cur].clear();
        t[cur].l = l;
        t[cur].r = r;
        t[cur].siz = t[cur].len();
        t[cur].prio = rand();
        return cur;
    }
    inline void pushup(int cur) {
        t[cur].siz = t[lson].siz + t[rson].siz + t[cur].len();
        return;
    }
    int Merge(int x, int y) {
        if(!x) return y; if(!y) return x;
        if(t[x].prio < t[y].prio) {
            t[x].ch[1] = Merge(t[x].ch[1], y);
            pushup(x);
            return x;
        } else {
            t[y].ch[0] = Merge(x, t[y].ch[0]);
            pushup(y);
            return y;
        }
    }
    pair<int, int> Split(int cur, ll k) {
        if(!cur || !k) return make_pair(0, cur);
        pair<int, int> res;
        if(t[lson].siz >= k) {
            res = Split(lson, k);
            lson = res.second;
            pushup(cur);
            res.second = cur;
        } else if(t[lson].siz + t[cur].len() >= k) {
            register ll l = t[cur].l, r = t[cur].r;
            int newrt;
            k -= t[lson].siz;
            t[cur].rerange(l, l + k - 1ll);
            newrt = newnode(l + k, r);
            res.second = Merge(newrt, rson);
            rson = 0;
            if(t[cur].len() <= 0) cur = lson;
            pushup(cur);
            res.first = cur;
        } else {
        	res = Split(rson, k - t[lson].siz - t[cur].len());
            rson = res.first;
            pushup(cur);
            res.first = cur;
        }
        return res;
    }
    inline void build() {
        for(int i = 1; i <= n; ++i) 
            Root[i] = newnode(((ll)i - 1ll) * (ll)m + 1ll, (ll)i * (ll)m - 1ll);
        Root[0] = newnode((ll)m, (ll)m);
        int cur;
        for(int i = 2; i <= n; ++i) {
            cur = newnode((ll)i * (ll)m, (ll)i * (ll)m);
            Root[0] = Merge(Root[0], cur);
        }
        return;
    }
    inline void work(ll x, ll y) {
        pair<int, int> pre1, per1, pre2, per2;
        if(y != m) {
            pre1 = Split(Root[0], x);
            per1 = Split(pre1.first, x - 1ll);
            pre2 = Split(Root[x], y);
            per2 = Split(pre2.first, y - 1ll);
            printf("%lld
    ", t[per2.second].l);
            Root[0] = Merge(Merge(per1.first, pre1.second), per2.second);
            Root[x] = Merge(Merge(per2.first, pre2.second), per1.second);
        } else {
            pre1 = Split(Root[0], x);
            per1 = Split(pre1.first, x - 1ll);
            printf("%lld
    ", t[per1.second].l);
            Root[0] = Merge(Merge(per1.first, pre1.second), per1.second);
        }
        return;
    }
    
    int main() {
    //	freopen("dui.in", "r", stdin);
    //	freopen("dui.out", "w", stdout);
        srand(time(NULL));
        scanf("%d%d%d", &n, &m, &q);
        build();
        ll x, y;
        while(q--) {
            scanf("%lld%lld", &x, &y);
            work(x, y);
        }
    //    fclose(stdin);
    //    fclose(stdout);
        return 0;
    }
    
    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    【转载】SAP_ECC6.0_EHP4或SAP_ECC6.0_EHP5_基于Windows_Server_2008R2_和SQL_server_2008下的安装
    使用delphi 开发多层应用(二十四)KbmMW 的消息方式和创建WIB节点
    使用delphi 开发多层应用(二十三)KbmMW 的WIB
    实现KbmMw web server 支持https
    KbmMW 服务器架构简介
    Devexpress VCL Build v2014 vol 14.1.1 beta发布
    使用delphi 开发多层应用(二十二)使用kbmMW 的认证管理器
    KbmMW 4.50.00 测试版发布
    Basic4android v3.80 beta 发布
    KbmMW 认证管理器说明(转载)
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9343474.html
Copyright © 2011-2022 走看看