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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct Fenwick {
int n;
vector<long long> f;
Fenwick() {}
Fenwick(int n): n(n), f(n+2, 0) {}
void reset() { fill(f.begin(), f.end(), 0); }
void add(int i, long long v){ for(; i<=n+1; i+=i&-i) f[i]+=v; }
long long sum(int i){ long long s=0; for(; i>0; i-=i&-i) s+=f[i]; return s; }
};
struct PST {
struct Node { int l, r, s; };
int n;
vector<Node> t;
vector<int> root; // versions by Euler time
PST(int n): n(n) {
t.reserve(n * 40);
t.push_back({0,0,0}); // node 0: null
root.assign(n+1, 0);
}
int newnode(int from){
t.push_back(t[from]);
return (int)t.size()-1;
}
int upd(int prev, int L, int R, int pos){
int cur = newnode(prev);
t[cur].s = t[prev].s + 1;
if(L==R) return cur;
int mid = (L+R)>>1;
if(pos<=mid){
int nl = upd(t[prev].l, L, mid, pos);
t[cur].l = nl;
}else{
int nr = upd(t[prev].r, mid+1, R, pos);
t[cur].r = nr;
}
return cur;
}
// kth in (A = subtree(L)) \ (B = subtree(c)) using versions
int kth_diff(int aR, int aL, int bR, int bL, int L, int R, int k){
if(L==R) return L;
int aLch = t[aL].l, aRch = t[aR].l;
int bLch = t[bL].l, bRch = t[bR].l;
int leftCnt = (t[aRch].s - t[aLch].s) - (t[bRch].s - t[bLch].s);
int mid = (L+R)>>1;
if(k<=leftCnt){
return kth_diff(aRch, aLch, bRch, bLch, L, mid, k);
}else{
int aLr = t[aL].r, aRr = t[aR].r;
int bLr = t[bL].r, bRr = t[bR].r;
return kth_diff(aRr, aLr, bRr, bLr, mid+1, R, k-leftCnt);
}
}
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
if(!(cin >> n >> q)) return 0;
vector<int> par(n+1);
int root = -1;
for(int i=1;i<=n;i++){
cin >> par[i];
if(par[i]==0) root = i;
}
vector<vector<int>> g(n+1);
for(int i=1;i<=n;i++) if(par[i]!=0) g[par[i]].push_back(i);
const int LOG = 17; // since n<=1e5
vector<array<int, 18>> up(n+1);
vector<int> depth(n+1,0), tin(n+1,0), tout(n+1,0), inv(n+1,0), sz(n+1,0);
// Iterative DFS for tin/tout, depth, up[0], sz
int timer = 0;
vector<pair<int,int>> st;
up[root][0] = 0;
depth[root]=0;
st.push_back({root, 0});
while(!st.empty()){
auto [u, state] = st.back(); st.pop_back();
if(state==0){
tin[u] = ++timer;
inv[timer] = u;
sz[u] = 1;
st.push_back({u, 1});
for(int v: g[u]){
up[v][0] = u;
depth[v] = depth[u] + 1;
st.push_back({v, 0});
}
}else{
for(int v: g[u]) sz[u] += sz[v];
tout[u] = timer;
}
}
for(int j=1;j<=LOG;j++){
for(int v=1; v<=n; v++){
up[v][j] = up[ up[v][j-1] ][j-1];
}
}
auto jump = [&](int x, int k){
for(int j=0;j<=LOG;j++){
if(k & (1<<j)) x = up[x][j];
}
return x;
};
// Persistent segment tree over labels 1..n, versions by Euler time
PST pst(n);
pst.root[0] = 0;
for(int i=1;i<=n;i++){
int id = inv[i]; // node id whose label is i
pst.root[i] = pst.upd(pst.root[i-1], 1, n, id);
}
// Build events for F_x(t): range-add via difference on Euler index
// At threshold t = node label l: +sz[l] on [tin[l], tout[l]]
// At threshold t = parent label of c: -sz[c] on [tin[c], tout[c]]
vector<vector<pair<int,int>>> events(n+2);
for(int l=1;l<=n;l++){
events[l].push_back({tin[l], sz[l]});
events[l].push_back({tout[l]+1, -sz[l]});
if(par[l]!=0){
int t = par[l];
events[t].push_back({tin[l], -sz[l]});
events[t].push_back({tout[l]+1, +sz[l]});
}
}
// Read queries: map k -> (x, r)
struct Query { long long k; int x; int r; };
vector<Query> qs(q);
for(int i=0;i<q;i++){
long long k; cin >> k;
int x = int((k-1) / n) + 1;
int r = int((k-1) % n) + 1;
qs[i] = {k, x, r};
}
// Parallel binary search to find label L for each query
vector<int> lo(q, 1), hi(q, n);
vector<vector<int>> buckets(n+2);
Fenwick bit(n+2);
while(true){
bool changed = false;
for(int t=1;t<=n;t++) buckets[t].clear();
for(int i=0;i<q;i++){
if(lo[i]<hi[i]){
int mid = (lo[i]+hi[i])>>1;
buckets[mid].push_back(i);
changed = true;
}
}
if(!changed) break;
bit.reset();
for(int t=1;t<=n;t++){
for(auto &ev: events[t]) bit.add(ev.first, ev.second);
for(int idx: buckets[t]){
int x = qs[idx].x;
long long val = bit.sum(tin[x]);
if(val >= qs[idx].r) hi[idx] = t;
else lo[idx] = t+1;
}
}
}
vector<int> L(q);
for(int i=0;i<q;i++) L[i] = lo[i];
// One more pass to get F_x(L-1)
vector<vector<int>> buck2(n+1);
for(int i=0;i<=n;i++) buck2[i].clear();
for(int i=0;i<q;i++){
int t = L[i]-1; if(t<0) t=0;
buck2[t].push_back(i);
}
vector<long long> Fless(q, 0);
bit.reset();
// t=0 first (no events applied)
for(int idx: buck2[0]){
int x = qs[idx].x;
(void)x; // value is zero at t=0
Fless[idx] = 0;
}
for(int t=1;t<=n;t++){
for(auto &ev: events[t]) bit.add(ev.first, ev.second);
for(int idx: buck2[t]){
int x = qs[idx].x;
Fless[idx] = bit.sum(tin[x]);
}
}
// Answer each query: find y within group L with rank pos = r - F(L-1)
for(int i=0;i<q;i++){
int x = qs[i].x;
int l = L[i];
int pos = qs[i].r - (int)Fless[i];
int c = 0;
if(l != x){
int k = depth[x] - depth[l] - 1;
c = jump(x, k);
}
int aR = pst.root[ tout[l] ];
int aL = pst.root[ tin[l]-1 ];
int bR = (c ? pst.root[ tout[c] ] : 0);
int bL = (c ? pst.root[ tin[c]-1 ] : 0);
int y = pst.kth_diff(aR, aL, bR, bL, 1, n, pos);
long long N = (long long)n;
long long res = (long long)(x-1) * N * N + (long long)(l-1) * N + (long long)(y-1);
cout << res << '\n';
}
return 0;
}
|