https://nanti.jisuanke.com/t/38229
題意:求樹上兩點間的邊權小於K的個數
題意:LCA在dfs預處理的時候建主席樹,利用前綴和(樹上同樣滿足), 然後這樣
int ans=query(1,n,root[llccaa],root[x],h)+query(1,n,root[llccaa],root[y],h);
求出兩點的LCA 就好了,就成樹上主席樹了 這裏用的倍增LCA
注意就是得離散化,
//預處理parent[v][k]:O(nlogn),單次查詢:O(logn)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node{
int l,r;
int sum;
}T[maxn*50];
struct edge{
int v,w;
int next;
}e[maxn*2];
int head[maxn],size,root[maxn],cnt,rt=1;
int n,m,dep[maxn],f[maxn][25],lg[maxn];
vector<int>v;
void add(int u,int v,int w){
e[size].v=v;
e[size].w=w;
e[size].next=head[u];
head[u]=size++;
}
int getid(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void update(int l,int r,int &x,int y,int pos){
T[++cnt]=T[y];
T[cnt].sum++;
x=cnt;
if(l==r) return ;
int mid=(l+r)/2;
if(pos<=mid) update(l,mid,T[x].l,T[y].l,pos);
else update(mid+1,r,T[x].r,T[y].r,pos);
}
int query(int l,int r,int L,int R,int k){//小於K的個數
if(r<=k) return T[R].sum-T[L].sum;
int mid=(l+r)/2;
int ls=T[T[R].l].sum-T[T[L].l].sum;
if(mid>=k) return query(l,mid,T[L].l,T[R].l,k);
else return ls+query(mid+1,r,T[L].r,T[R].r,k);
}
void dfs(int u,int fa,int d){
dep[u]=d;
f[u][0]=fa;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v; int w=e[i].w;
if(v!=fa){
update(1,n,root[v],root[u],getid(w));
dfs(v,u,d+1);
}
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
while(dep[u]!=dep[v]){
int d=dep[u]-dep[v];
if(lg[d]-1>=0) u=f[u][lg[d]-1];
else u=f[u][0];
}
if(u==v) return u;
for(int i=lg[dep[v]];i>=0;i--){
if(f[u][i]!=f[v][i]){
u=f[u][i];
v=f[v][i];
}
}
return f[u][0];
}
int init(){
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
dfs(rt,0,1); //無向圖根節點爲1
for(int j=1;j<=20;j++){
for(int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
}
}
}
int main(){
scanf("%d%d",&n,&m);
int N=n-1;
memset(head,-1,sizeof(head));
while(N--){
int x,y,z; scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
v.push_back(z);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
//離散化後操作的都是下標
init();
while(m--){
int x,y,k; scanf("%d%d%d",&x,&y,&k);
int llccaa=lca(x,y);
int h=upper_bound(v.begin(),v.end(),k)-v.begin();//注意這個二分
if(h!=0){
int ans=query(1,n,root[llccaa],root[x],h)+query(1,n,root[llccaa],root[y],h);
printf("%d\n",ans);
}
else{
puts("0");
}
}
return 0;
}