Dyd's Blog

He who has a strong enough why can bear almost any how.

luoguP4883 mzf的考验

“我的splay常数小”

mzf的考验

一开始要写平衡树我是拒绝的,但是没有办法,最讨厌的是它要求区间旋转,这就意味着只有FHQ和slpay可以搞(其它的我都搞不出区间旋转操作),最后,决定打splay(主要是FHQ不会),然后看到讨论区说这道题卡常的一笔,我留下了历史性的flag——“没事,我的splay常数小”

太久没写slpay,写的有点困难

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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 5e5 + 5, D = 20;
int n, m;
int p[D];
int a[N];
void update(int x[], int d)
{
for (int i = 0; i < D; ++i, d >>= 1)
x[i] = d & 1;
}
struct Splay
{
int root = 0, num = 0;
int as[D];
struct Node
{
int ch[2], fa, v, size, cnt[D], txor;
LL sum;
bool rev;
} tr[N];
#define ch(x, y) tr[(x)].ch[(y)]
#define sum(x) tr[(x)].sum
#define si(x) tr[(x)].size
#define rev(x) tr[(x)].rev
#define txor(x) tr[(x)].txor
#define cnt(x, y) tr[(x)].cnt[(y)]
#define fa(x) tr[(x)].fa
#define v(x) tr[(x)].v
void push_up(int x)
{
si(x) = si(ch(x, 1)) + si(ch(x, 0)) + 1;
sum(x) = sum(ch(x, 1)) + sum(ch(x, 0)) + v(x);
for (int i = 0; i < D; ++i)
cnt(x, i) = cnt(ch(x, 0), i) + cnt(ch(x, 1), i) + ((v(x) >> i) & 1);
}
void rotate(int x)
{
int y = fa(x), z = fa(y);
int k = ch(y, 1) == x;
ch(z, ch(z, 1) == y) = x, fa(x) = z;
ch(y, k) = ch(x, k ^ 1), fa(ch(x, k ^ 1)) = y;
ch(x, k ^ 1) = y, fa(y) = x;
push_up(y), push_up(x);
}
void splay(int x, int k)
{
if (x == k)
return ;
int y, z;
while (fa(x) != k)
{
y = fa(x), z = fa(y);
if (z != k)
(ch(y, 1) == x) ^ (ch(z, 1) == y) ? rotate(x) : rotate(y);
rotate(x);
}
if (!k)
root = x;
}
void tag_rev(int x)
{
if (!x)
return ;
swap(ch(x, 1), ch(x, 0));
rev(x) ^= 1;
}
void tag_xor(int x, int d)
{
if (!x)
return ;
update(as, d);
LL res = 0;
for (int i = 0; i < D; ++i)
{
if (as[i])
cnt(x, i) = si(x) - cnt(x, i);
res += (LL)cnt(x, i) * p[i];
}
sum(x) = res;
v(x) ^= d, txor(x) ^= d;
}
void push_donw(int x)
{
if (rev(x))
{
tag_rev(ch(x, 0)), tag_rev(ch(x, 1));
rev(x) = 0;
}
if (txor(x))
{
tag_xor(ch(x, 0), txor(x)), tag_xor(ch(x, 1), txor(x));
txor(x) = 0;
}
}
int get_k(int x, int k)
{
push_donw(x);
if (si(ch(x, 0)) + 1 == k)
return x;
if (k <= si(ch(x, 0)))
return get_k(ch(x, 0), k);
return get_k(ch(x, 1), k - si(ch(x, 0)) - 1);
}
void reve(int l, int r)
{
int ll = get_k(root, l), rr = get_k(root, r + 2);
splay(ll, 0), splay(rr, 0);
if (fa(ll) != root)
rotate(ll);
tag_rev(ch(ll, 1));
}
void cxor(int l, int r, int d)
{
int ll = get_k(root, l), rr = get_k(root, r + 2);
splay(ll, 0), splay(rr, 0);
if (fa(ll) != root)
rotate(ll);
tag_xor(ch(ll, 1), d);
push_up(ll), push_up(rr);
}
LL ask(int l, int r)
{
int ll = get_k(root, l), rr = get_k(root, r + 2);
splay(ll, 0), splay(rr, 0);
if (fa(ll) != root)
rotate(ll);
return sum(ch(ll, 1));
}
void build(int ff, int l, int r, int &x) //类似于线段树
{
if (l > r)
return ;
int mid = l + r >> 1;
x = ++num;
fa(x) = ff, v(x) = a[mid];
if (l == r)
{
si(x) = 1, sum(x) = v(x);
update(tr[x].cnt, v(x));
return ;
}
build(x, l, mid - 1, ch(x, 0));
build(x, mid + 1, r, ch(x, 1));
push_up(x);
}
void init(int x)
{
num = 2, root = 1;
ch(1, 1) = si(1) = 2;
fa(2) = si(2) = 1;
build(2, 1, n, ch(2, 0));
push_up(2), push_up(1);
}
} tr;
void prev()
{
p[0] = 1;
for (int i = 1; i < D; ++i)
p[i] = p[i - 1] << 1;
}
int main()
{
prev();
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
tr.init(n);
int op, l, r, x;
while (m--)
{
scanf("%d%d%d", &op, &l, &r);
if (op == 1)
tr.reve(l, r);
else if (op == 2)
scanf("%d", &x), tr.cxor(l, r, x);
else
printf("%lld\n", tr.ask(l, r));
}
return 0;
}

断断续续打了有2d,交的时候过去的话语犹在耳畔—— “我的splay常数小”,然后一交——TLE40分,wdf

果断无耻吸氧,含泪AC,完毕后不忘说一句: “我的splay开了O2常数小”