P3391 【模板】文艺平衡树 splay解法

P3391 【模板】文艺平衡树
splay解法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int ch[N][2], par[N], val[N], cnt[N], size[N], rev[N], root, ncnt;
int n, m, x, y;
void output(int x);
bool chk(int x) {
    return ch[par[x]][1] == x;
}
void pushup(int x) {
    size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x];
}
void pushdown(int x) {
    if (rev[x])  {
        swap(ch[x][0], ch[x][1]);
        rev[ch[x][0]] ^= 1;
        rev[ch[x][1]] ^= 1;
        rev[x] = 0;
    }
}
void rotate(int x) {
    int y = par[x], z = par[y], k = chk(x), w = ch[x][k^1];
    ch[y][k] = w; par[w] = y;
    ch[z][chk(y)] = x; par[x] = z;
    ch[x][k^1] = y; par[y] = x;
    pushup(y); pushup(x);
}
void splay(int x, int goal = 0) {
    while (par[x] != goal) {
        int y = par[x], z = par[y];
        if (z != goal) {
            if (chk(x) == chk(y)) rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
    if (!goal) root = x;
}
void insert(int x) {
    int cur = root, p = 0;
    while (cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x > val[cur]];
    }
    if (cur) {
        cnt[cur]++;
    } else {
        cur = ++ncnt;
        if (p) ch[p][x > val[p]] = cur;
        ch[cur][0] = ch[cur][1] = 0;
        par[cur] = p; val[cur] = x;
        cnt[cur] = size[cur] = 1;
    }
    splay(cur);
}
void find(int x) {
    int cur = root;
    while (ch[cur][x > val[cur]] && val[cur] != x) {
        cur = ch[cur][x > val[cur]];
    }
    splay(cur);
}
int kth(int k) {
    int cur = root;
    while (1) {
        pushdown(cur);
        if (ch[cur][0] && k <= size[ch[cur][0]]) {
            cur = ch[cur][0];
        } else if (k > size[ch[cur][0]] + cnt[cur]) {
            k -= size[ch[cur][0]] + cnt[cur];
            cur = ch[cur][1];
        } else {
            splay(cur);
            return cur;
        }
    }
}
 
void reverse(int l, int r) {
    int x = kth(l), y = kth(r+2);
    splay(x); splay(y, x);
    rev[ch[y][0]] ^= 1;
}
void output(int x) {
    pushdown(x);
    if (ch[x][0]) output(ch[x][0]);
    if (val[x] && val[x] <= n) printf("%d ", val[x]);
    if (ch[x][1]) output(ch[x][1]);
}
 
 
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n+1; i++) insert(i);
    while (m--) {
        scanf("%d%d", &x, &y);
        reverse(x, y);
    }
    output(root);
}

splay解法2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int Maxn=1000007;
const int inf=1e9;
int f[Maxn],cnt[Maxn],ch[Maxn][2],size[Maxn],key[Maxn],tag[Maxn],sz,rt;
int n,m,x,y,data[Maxn];
bool get(int x)
{
    return ch[f[x]][1]==x;
}
void pushup(int x)
{
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void pushdown(int x)
{
    if(x&&tag[x])
    {
        tag[ch[x][0]]^=1;
        tag[ch[x][1]]^=1;
        swap(ch[x][0],ch[x][1]);
        tag[x]=0;
    }
}
void rotate(int x)
{
    int old=f[x],oldf=f[old],which=get(x);
    pushdown(old);pushdown(x);
    ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;
    ch[x][which^1]=old;f[old]=x;
    f[x]=oldf;
    if(oldf) ch[oldf][ch[oldf][1]==old]=x;
    pushup(old);pushup(x);
}
void splay(int x,int goat)
{
    for (int fa;(fa=f[x])!=goat;rotate(x))
    {
        /*
        if (f[fa]!=goat)
        {
            rotate((get(x)==get(fa))?fa:x);
        }
        */
    }
    if(!goat) rt=x;
}
int bulid_tree(int fa,int l,int r)
{
    if (l>r) return 0;
    int mid=(l+r)>>1;
    int now=++sz;
    key[now]=data[mid];f[now]=fa;tag[now]=0;
    ch[now][0]=bulid_tree(now,l,mid-1);
    ch[now][1]=bulid_tree(now,mid+1,r);
    pushup(now);
    return now;
}
int rnk(int x)
{
    int now=rt;
    while(1)
    {
        pushdown(now);
        if (x<=size[ch[now][0]]) now=ch[now][0];
        else
        {
            x-=size[ch[now][0]]+1;
            if(!x) return now;
            now=ch[now][1];
        }
    }
}
void turn(int l,int r)
{
    l=rnk(l);
    r=rnk(r+2);
    splay(l,0);
    splay(r,l);
    pushdown(rt);
    tag[ch[ch[rt][1]][0]]^=1;
}
void write(int now)
{
    pushdown(now);
    if (ch[now][0]) write(ch[now][0]);
    if (key[now]!=-inf&&key[now]!=inf) cout<<key[now]<<" ";
    if (key[ch[now][1]]) write(ch[now][1]);
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++) data[i+1]=i;
    data[1]=-inf;data[n+2]=inf;
    rt=bulid_tree(0,1,n+2);
    for (int i=1;i<=m;i++)
    {
        cin>>x>>y;
        turn(x,y);
    }
    write(rt);
    return 0;
}

splay解法3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int Maxn=1000007;
const int inf=1e9;
int f[Maxn],cnt[Maxn],ch[Maxn][2],size[Maxn],key[Maxn],tag[Maxn],sz,rt;
int n,m,x,y,data[Maxn];
bool get(int x)
{
    return ch[f[x]][1]==x;
}
void pushup(int x)
{
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void pushdown(int x)
{
    if(x&&tag[x])
    {
        tag[ch[x][0]]^=1;
        tag[ch[x][1]]^=1;
        swap(ch[x][0],ch[x][1]);
        tag[x]=0;
    }
}
void rotate(int x)
{
    int old=f[x],oldf=f[old],which=get(x);
    pushdown(old);pushdown(x);
    ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;
    ch[x][which^1]=old;f[old]=x;
    f[x]=oldf;
    if(oldf) ch[oldf][ch[oldf][1]==old]=x;
    pushup(old);pushup(x);
}
void splay(int x,int goat)
{
    for (int fa;(fa=f[x])!=goat;rotate(x))
    {
        if (f[fa]!=goat)
        {
            rotate((get(x)==get(fa))?fa:x);
        }
    }
    if(!goat) rt=x;
}
int bulid_tree(int fa,int l,int r)
{
    if (l>r) return 0;
    int mid=(l+r)>>1;
    int now=++sz;
    key[now]=data[mid];f[now]=fa;tag[now]=0;
    ch[now][0]=bulid_tree(now,l,mid-1);
    ch[now][1]=bulid_tree(now,mid+1,r);
    pushup(now);
    return now;
}
int rnk(int x)
{
    int now=rt;
    while(1)
    {
        pushdown(now);
        if (x<=size[ch[now][0]]) now=ch[now][0];
        else
        {
            x-=size[ch[now][0]]+1;
            if(!x) return now;
            now=ch[now][1];
        }
    }
}
void turn(int l,int r)
{
    l=rnk(l);
    r=rnk(r+2);
    splay(l,0);
    splay(r,l);
    pushdown(rt);
    tag[ch[ch[rt][1]][0]]^=1;
}
void write(int now)
{
    pushdown(now);
    if (ch[now][0]) write(ch[now][0]);
    if (key[now]!=-inf&&key[now]!=inf) cout<<key[now]<<" ";
    if (key[ch[now][1]]) write(ch[now][1]);
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++) data[i+1]=i;
    data[1]=-inf;data[n+2]=inf;
    rt=bulid_tree(0,1,n+2);
    for (int i=1;i<=m;i++)
    {
        cin>>x>>y;
        turn(x,y);
    }
    write(rt);
    return 0;
}

  

 

posted @   心悟&&星际  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示