GEDT 2C

题目大意

你有一个长度为$n\le10^5$的整数序列$a$,满足$\forall a_i\in[0,m)$,其中$m\le10^9$。

你要支持$q\le10^5$个询问,给你两个整数$d\in[0,m),k\in[1,n]$,令$b_i=(ai+d)\bmod m$将$b$当成一个字符串,回答字典序第$k$小的后缀是哪一个。

暴力

考虑什么时候后缀数组会发生变化,就是与原来相比,存在至少一个元素原来是不被膜的,而某一次修改后被膜了

形式化地说:
$$
\exists a_i+d_{j-1}< m\le a_i+d_j
$$
又由于每个元素最多只会被膜一次,所以后缀数组的变化是$\mathcal O(n)$的。

那么就得到一个$O(n^2log)$的解法了。

暴力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
#define DREP(i, s, e) for(int i(s), end_##i(e); i >= end_##i ;i--)
#define REP(i, s, e) for(int i(s), end_##i(e); i <= end_##i ;i++)

#define DEBUG fprintf(stderr, "Passing [%s] in Line %d\n", __FUNCTION__, __LINE__)
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)

#include <tr1/unordered_map>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;
const int maxn = 1e3 + 10, maxq = 5e5 + 10, maxN = maxn << 1;

template <typename T> inline T read()
{
T ans(0), p(1);
char c = getchar();
while (!isdigit(c))
{
if (c == '-') p = -1;
c = getchar();
}
while (isdigit(c))
{
ans = ans * 10 + c - 48;
c = getchar();
}
return ans * p;
}

int n, m, q, a[maxn], b[maxn];

tr1::unordered_map <int, int> ch[maxN];
int cur, start, last, id[maxN], Max[maxN], ne[maxN], beg[maxN];
inline int newnode(int _Max, int _beg = 0, int _id = 0)
{
ch[++cur].clear();
Max[cur] = _Max;
beg[cur] = _beg;
id[cur] = _id;
return cur;
}
inline void extend(int c, int _id)
{
int v(last), u(newnode(Max[v] + 1, _id, _id));
for (; v && ch[v].find(c) == ch[v].end(); v = ne[v]) ch[v][c] = u;
if (!v) ne[u] = start;
else if (Max[v] + 1 == Max[ch[v][c]]) ne[u] = ch[v][c];
else
{
int Old(ch[v][c]), New(newnode(Max[v] + 1, _id));
ch[New] = ch[Old];
ne[New] = ne[Old];
ne[u] = ne[Old] = New;
for (; v && ch[v][c] == Old;v = ne[v]) ch[v][c] = New;
}
last = u;
}

int sa[maxn], dfn;

int bg[maxN], nex[maxN], to[maxN], e;
inline void add(int x, int y)
{
e++;
to[e] = y;
nex[e] = bg[x];
bg[x] = e;
}

vector <pair <int, int> > v[maxN];

inline void init()
{
e = 0;
ch[start = last = cur = 1].clear();
dfn = 0;
}
void dfs(int x)
{
if (id[x]) sa[++dfn] = id[x];
for (int i = bg[x]; i ; i = nex[i]) dfs(to[i]);
bg[x] = 0;
}

inline void build_tree()
{
REP(i, 1, cur)
v[ne[i]].push_back(make_pair(-b[beg[i] + Max[ne[i]]], i));
REP(i, 1, cur)
if (!v[i].empty())
{
sort(v[i].begin(), v[i].end());
REP(j, 0, v[i].size() - 1)
add(i, v[i][j].second);
v[i].clear();
}
}

inline void get_sa()
{
init();
DREP(i, n, 1) extend(b[i], i);
build_tree();
dfs(start);
}

int hh[maxn];

int ans[maxq];
pair <pair <int, int>, int> que[maxq];
bool cmp(pair <pair <int, int>, int> A, pair<pair <int, int>, int> B) {return A.first.first > B.first.first;}

int main()
{
#ifdef CraZYali
freopen("C.in", "r", stdin);
freopen("C.out", "w", stdout);
#endif
cin >> n >> m >> q;
const int mod = m;
REP(i, 1, n) hh[i] = a[i] = read<int>();
sort(hh + 1, hh + 1 + n);hh[0] = unique(hh + 1, hh + 1 + n) - hh - 1;
REP(i, 1, q)
{
int d(read<int>()), k(read<int>());
que[i] = make_pair(make_pair(d, k), i);
}
sort(que + 1, que + 1 + q);//, cmp);
REP(i, 1, n) b[i] = a[i];
get_sa();
int last = hh[0];
REP(i, 1, q)
{
int d(que[i].first.first), k(que[i].first.second), pos(que[i].second);
bool flag = 0;
while (hh[last] + d >= mod)
{
last--;
flag = 1;
}
if (flag)
{
REP(j, 1, n) b[j] = (a[j] + d) % mod;
get_sa();
}
ans[pos] = sa[k];
// REP(i, 1, n) printf("%d%c", sa[i], i == n ? '\n' : ' ');
}
REP(i, 1, q) printf("%d\n", ans[i]);
return 0;
}

满分做法

暴力启发了我们,要关注变化情况。

我们发现,一个元素最多被膜一次这个优美的性质。

我们考虑后缀树,惊讶的发现,一个元素的改变,其实对应着一个子树的$dfs$序的改变!

考虑到$dfs$序是一段段连续的区间,那么这个东西我们就可以考虑用平衡树维护了。

所以这题是一个后缀自动机建后缀树并用平衡树快速维护dfs序来生成后缀数组的毒瘤大数据结构。

Code

1
咕咕咕

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×