【Bzoj3223】文艺平衡树

来源和评测点

Bzoj3223
Codevs3303
Caioj1134

题目

【题目大意】
写一种数据结构,来维护一个有序数列,其中需要提供以下操作:翻转一个区间,
例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
【输入格式】
第一行为n,m
n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)
m表示翻转操作次数,接下来m行每行两个数[l,r]
数据保证 1<=l<=r<=n(n,m < =100000)
【输出格式】
输出一行n个数字,表示原始序列经过m次变换后的结果
【输入样例】
5 3
1 3
1 3
1 4
【输出样例】
4 3 2 1 5

分析

这道题建议自己多出几个小数据检验
主要就是利用伸展树这种比较灵活的数据结构来维护数列
中序遍历就是当前的状态
通过标记实现翻转

代码

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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//Zory-2017
//*******************头文件*******************
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
//*******************全局常量*******************
const int MAXN=100000;
//*******************全局定义*******************
struct pt
{
int son[2],f;
int c;
bool fz;
pt()
{
c=0;fz=0;
son[0]=son[1]=f=-1;
}
}p[MAXN+10];
//*******************伸展树*******************
void update(int x)
{
p[x].c=1;
int lc=p[x].son[0],rc=p[x].son[1];
if(lc>0) p[x].c+=p[lc].c;
if(rc>0) p[x].c+=p[rc].c;
}
void rev(int x)
{
if(p[x].fz==0) return;p[x].fz=0;
swap(p[x].son[0],p[x].son[1]);
int lc=p[x].son[0],rc=p[x].son[1];
if(lc>0) p[lc].fz^=1;
if(rc>0) p[rc].fz^=1;
}
void rotate(int x,int w)
{
int f=p[x].f,ff=p[f].f;
int pson=p[x].son[w];
if(pson>0) p[pson].f=f;
p[f].son[1-w]=pson;
if(p[ff].son[0]==f) p[ff].son[0]=x;
else if(p[ff].son[1]==f) p[ff].son[1]=x;
p[x].f=ff;
p[x].son[w]=f;
p[f].f=x;
update(f);
update(x);
}
int root;
int t[MAXN+10];
void splay(int x,int rt)
{
int s=0,i=x;
while(p[i].f!=rt) t[++s]=i,i=p[i].f;
t[++s]=rt;
while(s>0) rev(t[s--]);
while(p[x].f!=rt)
{
int f=p[x].f,ff=p[f].f;
if(p[f].f==rt)
{
if(p[f].son[0]==x) rotate(x,1);
else if(p[f].son[1]==x) rotate(x,0);
}
else
{
if(p[ff].son[0]==f and p[f].son[0]==x) rotate(f,1),rotate(x,1);
else if(p[ff].son[0]==f and p[f].son[1]==x) rotate(x,0),rotate(x,1);
else if(p[ff].son[1]==f and p[f].son[0]==x) rotate(x,1),rotate(x,0);
else if(p[ff].son[1]==f and p[f].son[1]==x) rotate(f,0),rotate(x,0);
}
}
if(rt==0) root=x;
}
int findrank(int rk)
{
int x=root;
while(x>0)
{
rev(x);
int lcc=p[x].son[0]<0?0:p[p[x].son[0]].c;
if(rk<=lcc) x=p[x].son[0];
else if(rk==lcc+1) return x;
else x=p[x].son[1],rk-=lcc+1;
}
}
//*******************接口*******************
int n;
void buildtree()
{
root=1;
p[n].f=n-1;update(n);
for(int i=n-1;i>=1;i--)
{
p[i].f=i-1;
p[i].son[1]=i+1;
update(i);
}
p[0].son[1]=1;
}
void solve(int l,int r)
{
if(l==1 and r==n)
{
p[root].fz^=1;
}
else if(l==1 and r<n)
{
int y=findrank(r+1);
splay(y,0);
p[p[y].son[0]].fz^=1;
}
else if(l>1 and r==n)
{
int x=findrank(l-1);
splay(x,0);
p[p[x].son[1]].fz^=1;
}
else
{
int x=findrank(l-1);
int y=findrank(r+1);
splay(x,0);
splay(y,x);
p[p[y].son[0]].fz^=1;
}
}
void pf(int x)
{
if(x<0) return;
rev(x);
pf(p[x].son[0]);
printf("%d ",x);
pf(p[x].son[1]);
}
//*******************主函数*******************
int main()
{
int m;scanf("%d%d",&n,&m);
buildtree();
while(m--)
{
int l,r;scanf("%d%d",&l,&r);
if(l>r) swap(l,r);solve(l,r);
}
pf(root);
}

本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
本文地址:http://zory.cf/2017-12/文艺平衡树.html
转载请注明出处,谢谢!

哪怕是一杯奶茶,也将鼓励我继续创作!
0%