• 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/
  • 相关阅读:
    网上流行的学生选课相关的50个常用sql语句
    the interview questions of sql server
    ASP.NET 之 Chart Control for .Net Framework
    SQL Server之纵表与横表互转
    ASP.NET控件之RadioButtonList
    SQL Server通过钉钉机器人直接发送消息
    使用AMO对象,更改款属性名称
    常用MDX函数
    Excel 插入图片
    Sql Server 2008查询数据库中各表记录行数
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9343474.html
Copyright © 2020-2023  润新知