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\n", top);
    while(spl[x].fa != top) {
        //if(num <= 5) num++, printf("\n%d %d\n", 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 \n");
            int l = find_l(rt[v]);
            //printf("3\n");
            splaying(v, l, 0);
            //printf("2\n");
            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("\n");
    }
    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

猜你喜欢

转载自www.cnblogs.com/linglinga/p/12014032.html