👏
ABC239 E - Subtree K-th Max
問題概要
問題文
頂点の根付き木が与えられる。根は N である。また、頂点 1 には整数 i が書かれている。 X_i
個のクエリが与えられる。 Q 番目のクエリでは、整数の組 i が与えられるので、次の問題に答えよ。 (V_i,K_i)
- 問題:頂点
の部分木に含まれる頂点に書かれた整数のうち、 V_i 番目に大きいものを求めよ。 K_i
制約
1\leq N\leq 10^5 0\leq X\leq 10^9 1\leq Q\leq 10^5 1\leq V_i\leq N 1\leq K_i\leq 20 - 頂点
の部分木は頂点をV_i 個以上持つK_i - 入力はすべて整数
解説
愚直(?)解
標準ライブラリのデータ構造でできる..はず。
std::multiset
とかを使えばいい。
このとき、
が成り立つ。これを使うと、DFSとかで帰りがけ順に探索すれば
実装例(TLE)
#include<bits/stdc++.h>
using namespace std;
using graph = vector<vector<int>>;
int main() {
int n, q;
cin >> n >> q;
vector<int> x(n);
for (int i = 0; i < n; i++) {
cin >> x[i];
}
graph g(n);
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
a--;
b--;
g[a].push_back(b);
g[b].push_back(a);
}
vector<multiset<int>> S(n);
auto dfs = [&](auto f, int v, int par = -1)-> void {
S[v].insert(x[v]); //x[v]を追加する
for (auto c : g[v]) {
if (c == par)continue; //親ならcontinue
f(f, c, v); //S[v]を構築する
//S[v] <- S[v] ∪ S[c]
for (auto el : S[c]) {
S[v].insert(el);
}
}
};
dfs(dfs, 0);
while (q--) {
int v, k;
cin >> v >> k;
v--;
auto itr = S[v].end();
for (int i = 0; i < k; i++) {
itr--;
}
cout << (*itr) << endl;
}
}
高速化
これだとTLEする。なぜなら、
と更新するとき、一直線とかになると
具体例
上のようなグラフについて、
-
を構成するとき、S_4 より|S_5|=1 回1 -
を構成するとき、S_3 より|S_4|=2 回2 -
を構成するとき...S_2
...
みたいになって、計算量が
...再び
ということで、
としたあと、
実装例(AC)
計算量は...定数倍が
#include<bits/stdc++.h>
using namespace std;
using graph = vector<vector<int>>;
int main() {
int n, q;
cin >> n >> q;
vector<int> x(n);
for (int i = 0; i < n; i++) {
cin >> x[i];
}
graph g(n);
for (int i = 0; i < n - 1; i++) {
int a, b;
cin >> a >> b;
a--;
b--;
g[a].push_back(b);
g[b].push_back(a);
}
vector<multiset<int>> S(n);
auto dfs = [&](auto f, int v, int par = -1)-> void {
S[v].insert(x[v]);
for (auto c : g[v]) {
if (c == par)continue;
f(f, c, v);
for (auto el : S[c]) {
S[v].insert(el);
}
}
//ここを追加した
while (S[v].size() > 20) {
S[v].erase(S[v].begin());
}
};
dfs(dfs, 0);
while (q--) {
int v, k;
cin >> v >> k;
v--;
auto it = S[v].end();
for (int i = 0; i < k; i++) {
it--;
}
cout << (*it) << endl;
}
}
あんまり賢いことしなくても良いという話でした。
Discussion