【2021牛客寒假第二场】F题 牛牛与交换排序 平衡树区间翻转

传送门:https://ac.nowcoder.com/acm/contest/9982/F

题意

给一个序列,让你找一个k,k代表区间,从左到右可以将区间翻转,问可以不可以将整个序列升序排列。

思路

赛中的这道题,大多数都是暴力过的,可能是数据太弱了。

一开始就能想到的就是splay区间翻转了。

Code

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
158
159
160
161
##include "bits/stdc++.h"

using namespace std;

typedef long long ll;

##define INF 0x3f3f3f3f

const int N = 1e5 + 10;

int a[N];
int n, cnt, root;

struct Node {
int ch[2];
int val, fa;
int siz, tag;
} t[N];

void update(int x) {
t[x].siz = t[t[x].ch[0]].siz + t[t[x].ch[1]].siz + 1;
}

void push_down(int x) {
if (x && t[x].tag) {
t[t[x].ch[0]].tag ^= 1;
t[t[x].ch[1]].tag ^= 1;
swap(t[x].ch[0], t[x].ch[1]);
t[x].tag = 0;
}
}

int id(int x) {
return x == t[t[x].fa].ch[1];
}

void connect(int fa, int x, int d) {
t[x].fa = fa;
t[fa].ch[d] = x;
}

void rotate(int x) {
int f = t[x].fa;
int ff = t[f].fa;
push_down(x);
push_down(f);
int fson = id(x);
int ffson = id(f);
int son = t[x].ch[fson ^ 1];
connect(f, son, fson);
connect(x, f, fson ^ 1);
connect(ff, x, ffson);
update(f), update(x);
}

void splay(int x, int to) { // 将 x 转到 to 的子节点位置
while (t[x].fa != to) {
int f = t[x].fa;
if (t[f].fa != to) {
rotate(id(x) == id(f) ? f : x);
}
rotate(x);
}
if (!to) { // 在 splay(l, 0) 时起作用
root = x;
}
}

int build(int l, int r, int fa) {
if (l > r) {
return 0;
}
int mid = (l + r) >> 1;
int x = ++cnt;
t[x].fa = fa;
t[x].siz = 1;
t[x].val = a[mid];
t[x].ch[0] = build(l, mid - 1, x);
t[x].ch[1] = build(mid + 1, r, x);
update(x);
return x;
}

int find(int rank) {
int x = root;
while (1) {
push_down(x);
if (rank <= t[t[x].ch[0]].siz) {
x = t[x].ch[0];
} else {
rank -= t[t[x].ch[0]].siz + 1;
if (!rank) {
return x;
}
x = t[x].ch[1];
}
}
}

void reverse(int l, int r) {
l = find(l);
r = find(r);
splay(l, 0);
splay(r, l);
int pos = t[t[root].ch[1]].ch[0];
t[pos].tag ^= 1;
}

void print(int x) {
if (!x) {
return;
}
push_down(x);
print(t[x].ch[0]);
if (t[x].val != INF && t[x].val != -INF) {
printf("%d ", t[x].val);
}
print(t[x].ch[1]);
}

void solve(){
int k = 0;
cin >> n;
for (int i = 1;i <= n; ++i) {
cin >> a[i + 1];
}
a[1] = -INF; a[n + 2] = INF;
for (int i = 1; i <= n; ++i) {
if (i != a[i + 1]) {
for (int j = i + 1; j <= n; ++j) {
if (i == a[j + 1]) {
k = j - i + 1;
break;
}
}
break;
}
}
//cout<<k<<endl;
if (k == 0) {
cout<< "yes" << endl << 1 << endl;
}
else{
root=build(1, n + 2, 0);
bool flag = false;
for(int i = 1;i <= n - k + 1; i++) {
if(t[find(i + 1)].val != i) {
if(t[find(i + k)].val != i) {
cout << "no" << endl;
return ;
}
reverse(i, i + k + 1);
}
}
cout << "yes" << endl << k << endl;
}
}

signed main() {
solve();
}

本文作者:jujimeizuo
本文地址https://blog.jujimeizuo.cn/2021/02/03/2021-nowcoder-hanjia-2-f/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!