题解 运输
题目描述
具体做法与心路历程
一开始没想到正解,于是开始码 O ( m w ) O(mw) O(mw)的暴力,码暴力的时候发现了正解。
具体做法
考虑将询问离线下来,然后差分到树上,暴力的方法就是在 d f s dfs dfs树的时候用一个数组 a n s [ i ] ans[i] ans[i]表示从根走到当前节点,
经过的边在询问的电量为 i i i时所需要的最少次数。那么在 d f s dfs dfs时从对每个 a n s [ i ] ans[i] ans[i]维护一下即可。
正解即是对于某条边 w w w,我们发现它对 a n s ans ans的答案是可以整除分块的,那么我们用树状数组维护 a n s ans ans,整除分开统计即可。
时间复杂度为 O ( m w l o g w ) O(m\sqrt{w}logw) O(mwlogw)。
C o d e \mathcal{Code} Code
/*******************************
Author:galaxy yr
LANG:C++
Created Time:2019年11月04日 星期一 08时30分26秒
*******************************/
#include<cstdio>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
struct IO{
template<typename T>
IO & operator>>(T&res)
{
T q=1;char ch;
while((ch=getchar())<'0' or ch>'9')if(ch=='-')q=-q;
res=(ch^48);
while((ch=getchar())>='0' and ch<='9') res=(res<<1)+(res<<3)+(ch^48);
res*=q;
return *this;
}
}cin;
struct edge{
int to,next,w;
edge(int a=0,int b=0,int c=0):to(a),next(b),w(c){}
};
struct Node{
int id,q,w;
Node(int a=0,int b=0,int c=0):id(a),q(b),w(c){}
};
const int maxn=1e5+10;
const int LG=20;
const int LIM=3e4;
int n,m,head[maxn],cnt,s[maxn],prime[maxn],tot,ans[maxn],f[maxn][LG+1],depth[maxn];
bool vis[maxn];
edge e[maxn<<1];
vector<Node>V[maxn];
/*{{{BIT*/
namespace BIT{
int tr[31000];
void add(int x,int val)
{
while(x<=LIM)
{
tr[x]+=val;
x+=x&-x;
}
}
int sum(int x)
{
int res=0;
while(x)
{
res+=tr[x];
x-=x&-x;
}
return res;
}
};
/*}}}*/
void add(int u,int v,int w)
{
e[++cnt]=edge(v,head[u],w);
head[u]=cnt;
}
void pre_dfs(int now)
{
depth[now]=depth[f[now][0]]+1;
for(int i=1;i<=LG;i++)
f[now][i]=f[f[now][i-1]][i-1];
for(int i=head[now];i;i=e[i].next)
if(e[i].to!=f[now][0])
{
f[e[i].to][0]=now;
pre_dfs(e[i].to);
}
}
int LCA(int x,int y)
{
if(depth[x]<depth[y]) swap(x,y);
for(int i=LG;i>=0;i--)
if(depth[f[x][i]]>=depth[y])
x=f[x][i];
if(x==y) return x;
for(int i=LG;i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
void update(int w,int q)
{
w--;
int d;
for(int l=1,r;l<=w;l=r+1)
{
r=w/(w/l);
d=w/l;
BIT::add(l,d*q);
BIT::add(r+1,d*q*(-1));
}
}
void dfs(int now)
{
int w,id,q;
for(int i=0;i<(int)V[now].size();i++)
{
w=V[now][i].w,id=V[now][i].id,q=V[now][i].q;
ans[id]+=q*BIT::sum(w);
}
for(int i=head[now];i;i=e[i].next)
if(e[i].to!=f[now][0])
{
w=e[i].w;
update(w,1);
dfs(e[i].to);
update(w,-1);
}
}
signed main()
{
//freopen("delivery.in","r",stdin);
//freopen("delivery.out","w",stdout);
cin>>n>>m;
int u,v,w;
for(int i=1;i<n;i++)
{
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
pre_dfs(1);
for(int i=1;i<=m;i++)
{
cin>>u>>v>>w;
if(u==v){ ans[i]=0; continue; }
ans[i]=depth[u]+depth[v]-2*depth[LCA(u,v)]+1;
V[u].push_back(Node(i,1,w));
V[v].push_back(Node(i,1,w));
V[LCA(u,v)].push_back(Node(i,-2,w));
}
dfs(1);
for(int i=1;i<=m;i++)
{
if(ans[i]==0) ans[i]=1;
printf("%lld\n",ans[i]);
}
return 0;
}