Distance on the tree(数剖 + 主席树)
题目链接:https://nanti.jisuanke.com/t/38229
题目大意:给你n个点,n-1条边,然后是m次询问,每一次询问给你u,v,w然后问你从u -> v 的路径上有多少边是小于等于w的、
AC代码:
1 #include<iostream> 2 #include<cmath> 3 #include<stack> 4 #include<queue> 5 #include<stdio.h> 6 #include<string> 7 #include<cstring> 8 #include<algorithm> 9 using namespace std; 10 # define inf 0x3f3f3f3f 11 # define ll long long 12 const int maxn = 3e5+100; 13 int n,m,num,tot,cnt,totn; 14 int a[maxn]; 15 int head[maxn]; 16 int root[maxn]; 17 struct Query 18 { 19 int l,r,tt; 20 } que[maxn]; 21 struct Tree 22 { 23 int ls,rs,sum; 24 } tr[maxn*16]; 25 struct Edge 26 { 27 int from,to,val,s; 28 } edges[maxn<<1]; 29 void addedge(int x,int y,int z) 30 { 31 edges[++tot]=Edge{x,y,z,head[x]}; 32 head[x]=tot; 33 } 34 int d[maxn],fa[maxn],size[maxn],w[maxn]; 35 int son[maxn]; 36 int rk[maxn],kth[maxn],top[maxn]; 37 void dfs1(int u,int pre,int val) 38 { 39 40 d[u]=d[pre]+1; 41 fa[u]=pre; 42 size[u]=1; 43 w[u]=val; 44 for(int i=head[u]; i!=-1; i=edges[i].s) 45 { 46 Edge &e=edges[i]; 47 if(e.to==pre) 48 continue; 49 dfs1(e.to,u,e.val); 50 size[u]+=size[e.to]; 51 if(size[e.to]>size[son[u]]) 52 son[u]=e.to; 53 } 54 } 55 void dfs2(int u,int y) 56 { 57 rk[u]=++cnt; 58 kth[cnt]=u; 59 top[u]=y; 60 if(son[u]==0) 61 return ; 62 dfs2(son[u],y); 63 for(int i=head[u]; i!=-1; i=edges[i].s) 64 { 65 Edge &e=edges[i]; 66 if(e.to==son[u]||e.to==fa[u]) 67 continue; 68 dfs2(e.to,e.to); 69 } 70 } 71 void buildtree(int &x,int l,int r) 72 { 73 x=++totn; 74 if(l==r) 75 return ; 76 int mid=(l+r)>>1; 77 buildtree(tr[x].ls,l,mid); 78 buildtree(tr[x].rs,mid+1,r); 79 } 80 void add(int &x,int last,int l,int r,int p) 81 { 82 x=++totn; 83 tr[x]=tr[last]; 84 if(l==r) 85 { 86 tr[x].sum++; 87 return ; 88 } 89 int mid=l+r>>1; 90 if(p<=mid) 91 add(tr[x].ls,tr[last].ls,l,mid,p); 92 if(p> mid) 93 add(tr[x].rs,tr[last].rs,mid+1,r,p); 94 tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum; 95 } 96 int ask(int ql,int qr,int l,int r,int kk) 97 { 98 if(1<=l&&r<=kk) 99 return tr[qr].sum-tr[ql].sum; 100 int mid=l+r>>1,ans=0; 101 if(1<=mid) 102 ans+=ask(tr[ql].ls,tr[qr].ls,l,mid,kk); 103 if(mid<kk) 104 ans+=ask(tr[ql].rs,tr[qr].rs,mid+1,r,kk); 105 return ans; 106 } 107 int get_sum(int x,int y,int tt) 108 { 109 int ans=0; 110 int fx=top[x],fy=top[y]; 111 while(fx!=fy) 112 { 113 if(d[fx]<d[fy]) 114 swap(x,y),swap(fx,fy); 115 ans+=ask(root[rk[fx]-1],root[rk[x]],1,num,tt); 116 x=fa[fx]; 117 fx=top[x]; 118 } 119 if(d[x]<d[y]) 120 swap(x,y); 121 ans+=ask(root[rk[y]],root[rk[x]],1,num,tt); 122 return ans; 123 } 124 int main() 125 { 126 scanf("%d %d",&n,&m); 127 ll x,y,z,id,ans; 128 for(int i=0; i<=n; i++) 129 { 130 head[i]=-1; 131 } 132 for(int i=1; i<=n-1; i++) 133 { 134 scanf("%d %d %d",&x,&y,&z); 135 a[++num]=z; 136 addedge(x,y,z); 137 addedge(y,x,z); 138 } 139 for(int i=1; i<=m; i++) 140 { 141 scanf("%d %d %d",&que[i].l,&que[i].r,&que[i].tt); 142 a[++num]=que[i].tt; 143 } 144 sort(a+1,a+num+1); 145 num=unique(a+1,a+num+1)-a-1; 146 dfs1(1,0,inf); 147 dfs2(1,1); 148 for(int i=1; i<=n; i++) 149 { 150 w[i]=lower_bound(a+1,a+num+1,w[i])-a; 151 } 152 buildtree(root[0],1,num); 153 for(int i=1; i<=n; i++) 154 { 155 add(root[i],root[i-1],1,num,w[kth[i]]); 156 } 157 for(int i=1; i<=m; i++) 158 { 159 que[i].tt=lower_bound(a+1,a+num+1,que[i].tt)-a; 160 int ans=get_sum(que[i].l,que[i].r,que[i].tt); 161 printf("%d\n",ans); 162 } 163 return 0; 164 }