E – Subtree K-th Max
题目描述:
n个点,每个点有一个权值x,n-1条边,每次询问都是询问以
v
为顶点的子树中底k
大的值
思路:
根据数据范围发现k最大是20,所以对于每个顶点
v
,我们可以暴力维护以v
为根的子树中最大的20个数我开始用的是小根堆,处理和输出的时候不是特别方便。
后来发现可以用vector,又快有方便
如果这个题的K是1e5,那我们就可以使用dfs序 + ST表来处理
优先队列版:
//Work by: Chelsea
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod 1000000007
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d %d",&n,&m)
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 300000 + 50
int n, m, k, op;
int x, y, z;
ll a, b, c;
string s, t;
vector<int>tr[MAX];
int val[MAX];
priority_queue<int, vector<int>, greater<int> >q[100005];
bool vis[MAX];
void dfs(int u, int fa){
if(vis[u])return;
vis[u] = 1;
// cout << u << ' ' << fa << endl;
q[u].push(val[u]);
if(q[u].size() == 0)return;
for(auto v : tr[u]){
if(v == fa)continue;
dfs(v, u);
q[0] = q[v];
while(!q[0].empty()){
x = q[0].top();q[0].pop();
q[u].push(x);
}
while(q[u].size() > 20)q[u].pop();
}
return;
}
void work(){
cin >> n >> m;
for(int i = 1; i <= n; ++i)cin >> val[i];
for(int i = 1; i <= n - 1; ++i){
cin >> x >> y;
tr[x].push_back(y);
tr[y].push_back(x);
}
dfs(1, -1);
while (m--){
cin >> x >> y;
// cout << x << ' ' << y << endl;
q[0] = q[x];
while (q[0].size() != y) {
q[0].pop();
}
cout << q[0].top() << endl;
while (!q[0].empty()) {
q[0].pop();
}
}
}
int main(){
io;
work();
return 0;
}
vector版
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod 1000000007
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 300000 + 50
int n, m;
int x, y;
vector<int>tr[MAX];
vector<int>vv[MAX];
int val[MAX];
void dfs(int u, int fa){
// cout << u << ' ' << fa << endl;
vv[u].push_back(val[u]);
for(auto v : tr[u]){
if(v == fa)continue;
dfs(v, u);
for(auto x : vv[v])vv[u].push_back(x);
}
sort(vv[u].begin(), vv[u].end(), greater<int>());
while (vv[u].size() > 21) {
vv[u].pop_back();
}
return;
}
void work(){
cin >> n >> m;
for(int i = 1; i <= n; ++i)cin >> val[i];
for(int i = 1; i <= n - 1; ++i){
cin >> x >> y;
tr[x].push_back(y);
tr[y].push_back(x);
}
dfs(1, -1);
while (m--) {
cin >> x >> y;
cout << vv[x][y - 1] << endl;
}
}
int main(){
io;
work();
return 0;
}