ST 表算法用于查询区间最值,为静态算法,查询区间最值时不能更新信息,预处理复杂度为 O(nlongn),查询为 O(1)。适用于不更新信息且查询很多的问题。
题意:首先要计算出各个可到达点之间的长度,然后利用区间查找求解!
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxx=4e4+10;;
const int inf=0x3f3f3f3f;
int a[maxx];
int n,q;
int m;
int maxsum[maxx][20],minsum[maxx][20];
struct node{
int v,cost;
node(int v1,int cost1):v(v1),cost(cost1){}
};
vector<node>G[maxx];
void dfs(int u,int fa){
for(int i=0;i<G[u].size();i++){
int v=G[u][i].v;
int w=G[u][i].cost;
if(v==fa)continue;
a[v]=a[u]+w;
dfs(v,u);
}
}
void RMQ(){
for(int i=1;i<=n;i++){
maxsum[i][0]=minsum[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
minsum[i][j]=min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
maxsum[i][j]=max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
}
}
}
int maxl,minl;
void Query(int l,int r){
int k=(int)((log(r-l+1))/log(2.0));
maxl=max(maxsum[l][k],maxsum[r-(1<<k)+1][k]);
minl=min(minsum[l][k],minsum[r-(1<<k)+1][k]);
cout<<maxl-minl<<endl;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
memset(a,0,sizeof(a));
memset(maxsum,0,sizeof(maxsum));
memset(minsum,0,sizeof(minsum));
for(int i=1;i<=n;i++){
G[i].clear();
}
for(int i=1;i<=n-1;i++){
int a,b,cost;
scanf("%d %d %d",&a,&b,&cost);
G[a].push_back(node(b,cost));
G[b].push_back(node(a,cost));
}
dfs(1,-1);
RMQ();
for(int i=1;i<=m;i++){
int left,right;
scanf("%d %d",&left,&right);
if(left>right)swap(left,right);
Query(left,right);
}
}
return 0;
}