题目链接
你要是真暴力这道题还是要T的,但是,做了剪枝就会过了,我们知道对于LCA每个节点有它自己的深度,在这里,我就将每个节点的深度数组当作了每个节点道最初根节点的距离了。
然后,就是剪枝操作饿了:判断是否是可行解的时候用的是dis[x]+dis[y]-2*dis[lca(x, y)]+1与Kth的大小关系即可,不然真会T,我试过。
还有,别读了道假题做半天,题目让你求的是区间第K大,然后题目的测试样例又给的很巧,所以,千万要看清了!
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define efs 1e-6
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 80005;
int N, Q, a[maxN], cnt, head[maxN], depth[maxN], root[maxN][20], inque[maxN], num;
bool cmp(int e1, int e2) { return e1>e2; }
struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN<<1];
void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
void dfs(int u, int fa, int deep)
{
root[u][0] = fa;
depth[u] = deep;
for(int i=head[u]; i!=-1; i=edge[i].nex)
{
int v = edge[i].to;
if(v == fa) continue;
dfs(v, u, deep+1);
}
}
void pre_did()
{
dfs(1, -1, 0);
for(int j=0; ((1<<(j+1))<N); j++)
{
for(int i=1; i<=N; i++)
{
if(root[i][j]<0) root[i][j+1] = -1;
else root[i][j+1] = root[root[i][j]][j];
}
}
}
int LCA(int x, int y)
{
if(depth[x] > depth[y]) swap(x, y);
int deth = depth[y] - depth[x];
for(int i=(int)log2(1.*deth); i>=0; i--)
{
if((1<<i) & deth) y = root[y][i];
}
if(x == y) return x;
for(int i=(int)log2(1.*N); i>=0; i--)
{
if(root[x][i] != root[y][i])
{
x = root[x][i];
y = root[y][i];
}
}
return root[x][0];
}
void query(int x, int y, int Kth)
{
int fa = LCA(x, y);
if(depth[x] + depth[y] - 2*depth[fa] + 1 < Kth) { printf("invalid request!\n"); return; }
num = 0;
inque[++num] = a[fa];
while(x != fa)
{
inque[++num] = a[x];
x = root[x][0];
}
while(y != fa)
{
inque[++num] = a[y];
y = root[y][0];
}
sort(inque+1, inque+1+num, cmp);
printf("%d\n", inque[Kth]);
}
void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
memset(root, -1, sizeof(root));
}
int main()
{
scanf("%d%d", &N, &Q);
for(int i=1; i<=N; i++) scanf("%d", &a[i]);
init();
for(int i=1; i<N; i++)
{
int e1, e2;
scanf("%d%d", &e1, &e2);
addEddge(e1, e2);
addEddge(e2, e1);
}
pre_did();
int op, L, R;
while(Q--)
{
scanf("%d%d%d", &op, &L, &R);
if(op == 0) a[L] = R;
else query(L, R, op);
}
return 0;
}