• 2019牛客国庆集训派对day1 K题 双向链表练习题 splay区间翻转


    题目链接:

    解法:

    先建n颗平衡树,合并的时候将a中最右的结点翻转到根节点,b中最左的结点翻转到根节点,对合并后的根节点进行标记。

    #include <bits/stdc++.h>
    using namespace std;
    #define ls(p) p << 1
    #define rs(p) p << 1 | 1
    const int M = 1e5 + 10;
    int n, m, cnt;
    int rt[M];
    struct node{
        int fa, ch[2], val, cnt, sz, lazy;
    }spl[M];
    bool ident(int x, int f) {
        return spl[f].ch[1] == x;
    }
    void connect(int x, int f, int s){
        spl[f].ch[s] = x;
        spl[x].fa = f;
    }
    void update(int now) {
        spl[now].sz = spl[spl[now].ch[0]].sz + spl[spl[now].ch[1]].sz + spl[now].cnt;
    }
    void push_down(int now) {
        if(!spl[now].lazy) return;
        swap(spl[now].ch[0], spl[now].ch[1]);
        spl[spl[now].ch[0]].lazy ^= 1;
        spl[spl[now].ch[1]].lazy ^= 1;
        spl[now].lazy = 0;
    }
    void rotate(int x) {
        int f = spl[x].fa, ff = spl[f].fa, k = ident(x, f);
        connect(spl[x].ch[k ^ 1], f, k);
        connect(x, ff, ident(f, ff));
        connect(f, x, k ^ 1);
        update(f), update(x);
    }
    void splaying(int p, int x, int top) {
        if(!top) rt[p] = x;
        //printf("top = %d
    ", top);
        while(spl[x].fa != top) {
            //if(num <= 5) num++, printf("
    %d %d
    ", x, top);
            int f = spl[x].fa, ff = spl[f].fa;
            if(ff != top) ident(f, ff) ^ ident(x, f) ? rotate(x) : rotate(f);
            rotate(x);
        }
    }
    int find_r(int now) {
        push_down(now);
        while(spl[now].ch[1]) {
            now = spl[now].ch[1];
            push_down(now);
        }
        return now;
    }
    int find_l(int now) {
        push_down(now);
        while(spl[now].ch[0]) {
            now = spl[now].ch[0];
            push_down(now);
        }
        return now;
    }
    void newnode(int now, int val) {
        spl[now].val = val;
        spl[now].sz = 1;
        spl[now].cnt = 1;
        spl[now].ch[0] = 0;
        spl[now].ch[1] = 0;
        spl[now].fa = 0;
        spl[now].lazy = 0;
    }
    void work(){
        for(int i = 1; i <= n; i++) {
            rt[i] = i;
            newnode(i, i);
        }
        for(int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            if(!rt[u]) {
                if(rt[v]){
                    rt[u] = rt[v];
                    spl[rt[u]].lazy ^= 1;
                    rt[v] = 0;
                }
            }
            else if(!rt[v]) {
                spl[rt[u]].lazy ^= 1;
            }
            else {
                int r = find_r(rt[u]);
                splaying(u, r, 0);
                //printf("1 
    ");
                int l = find_l(rt[v]);
                //printf("3
    ");
                splaying(v, l, 0);
                //printf("2
    ");
                connect(l, r, 1);
                spl[rt[u]].lazy ^= 1;
                rt[v] = 0;
                update(rt[u]);
            }
        }
    }
    void out(int now){
        if(!now) return;
        push_down(now);
        out(spl[now].ch[0]);
        printf("%d ", spl[now].val);
        out(spl[now].ch[1]);
    }
    int main(){
        while(~scanf("%d%d", &n, &m)){
            cnt = 0;
            work();
            printf("%d ", spl[rt[1]].sz);
            if(spl[rt[1]].sz) out(rt[1]);
            printf("
    ");
        }
        return 0;
    }
    /*
    999 5
    99 8
    8 99
    99 8
    7 99
    1 7
    */
    /*
    999 5
    1 3
    1 4
    1 5
    1 6
    1 7
    */
    View Code
  • 相关阅读:
    08-蓝图&单元测试
    07-多对多操作
    JAVA 判断字符串是否可转化为JSONObject、JSONArray
    git常用命令
    线程和进程的一些基本概念
    JavaWeb学习总结(七):通过Servlet生成验证码及其应用 (BufferedImage类)
    JavaWeb学习总结(十):Session简单使用
    Ubuntu16.04 安装maven
    Ubuntu16.04 安装redis
    Ubuntu16.04 下安装tomcat
  • 原文地址:https://www.cnblogs.com/linglinga/p/12014032.html
Copyright © 2020-2023  润新知