思路:树上倍增f[i][j]=f[f[i][j-1]][j-1]还有LCA的赶脚
#include <iostream> #include <algorithm> #include <cstdio> #include <set> #include <sstream> #include<string> #include<queue> #include<stack> #include<map> #include<cmath> #include<cctype> #include<cstring> #include<cstdlib> #define MAXX 100005 #define SIS std::ios::sync_with_stdio(false) #define ll long long #define INF 0x3f3f3f3f //#include<bits/stdc++.h> using namespace std; const int MAX =1e5+20; const double PI = 3.14159265359; //const int mod = 1e9 + 7; int a[200005],b[200005]; vector<int> vt[200005]; int f[200005][25],dep[200005]; void dfs(int p,int fa) { int x=fa; for(int k=19;k>=0;k--) { if(f[x][k]&&a[f[x][k]]<=a[p])///如果x往上跳2^k步这个点存在,且这个点的权值比a[p]要小,就跳到这个点再往上跳 x=f[x][k]; } if(a[x]>a[p]) f[p][0]=x; ///判断比a[p]大的点到底是x还是x的上面那个点 else f[p][0]=f[x][0]; for(int i=1;i<20;i++) f[p][i]=f[f[p][i-1]][i-1]; dep[p]=dep[fa]+1; int h=vt[p].size(); for(int i=0;i<h;i++) { int u=vt[p][i]; if(u==fa) continue; dfs(u,p); } } int main() { int n,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); vt[x].push_back(y); vt[y].push_back(x); } for(int i=1;i<=q;i++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); vt[n+i].push_back(u); vt[u].push_back(n+i); a[n+i]=c; b[i]=v;///终点 } dfs(1,0); for(int i=1;i<=q;i++) { int ans=0; int x=i+n; for(int k=19;k>=0;k--) if(dep[f[x][k]]>=dep[b[i]]) { ans+=(1<<k); x=f[x][k]; } printf("%d\n",ans); } return 0; }