# hdu 4729 树链剖分

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pb push_back
#define mp make_pair
#define Maxn 200010
#define Maxm 400010
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define inf 100000
#define lowbit(x) (x&(-x))
#define clr(x,y) memset(x,y,sizeof(x))
#define Mod 1000000007
using namespace std;
int val[Maxn];
int num[Maxn],cnt;
struct Point{
int val,i;
int operator <(const Point &temp) const{
return val<temp.val;
}
}lis[Maxn];
struct Edge{
int u,v,next;
int val;
}edge[Maxn*3];
struct Tree{
int l,r,c;
int *p;
int *q;
int mid(){
return (l+r)>>1;
}
}tree[Maxn*3];
void init()
{
e=0;id=0;
}
{
}
void BuildTree(int l,int r,int po)
{
tree[po].l=l,tree[po].r=r,tree[po].c=0;
tree[po].p=new int[r-l+2];
tree[po].q=new int[r-l+2];
tree[po].q[0]=0;
if(l==r)
return ;
int mid=tree[po].mid();
BuildTree(l,mid,lson(po));
BuildTree(mid+1,r,rson(po));
}
void update(int i,int c,int po)
{
if(tree[po].l==tree[po].r){
tree[po].p[++tree[po].c]=c;
tree[po].q[tree[po].c]=tree[po].q[tree[po].c-1]+c;
return ;
}
tree[po].p[++tree[po].c]=c;
tree[po].q[tree[po].c]=tree[po].q[tree[po].c-1]+c;
int mid=tree[po].mid();
if(i<=mid)
update(i,c,lson(po));
else
update(i,c,rson(po));
}
int getmin(int l,int r,int po)
{
if(l<=tree[po].l&&tree[po].r<=r){
return tree[po].p[1];
}
int mid=tree[po].mid();
if(r<=mid)
return getmin(l,r,lson(po));
else if(l>=mid+1)
return getmin(l,r,rson(po));
else{
return min(getmin(l,mid,lson(po)),getmin(mid+1,r,rson(po)));
}
}
LL getans(int l,int r,LL val,int po)
{
if(l<=tree[po].l&&tree[po].r<=r){
int pos=lower_bound(tree[po].p+1,tree[po].p+tree[po].c+1,val)-tree[po].p;
if(pos>tree[po].c){
cnt+=tree[po].c;
return tree[po].q[tree[po].c];
}
if(pos>1){
cnt+=pos-1;
return tree[po].q[pos-1];
}
return 0;
}
int mid=tree[po].mid();
if(r<=mid)
return getans(l,r,val,lson(po));
else if(l>=mid+1)
return getans(l,r,val,rson(po));
else{
return getans(l,mid,val,lson(po))+getans(mid+1,r,val,rson(po));
}
}
void dfs(int u,int val)
{
vi[u]=1;
int i,v;
son[u]=0,sz[u]=1;
num[u]=val;
v=edge[i].v;
if(vi[v]) continue;
dep[v]=dep[u]+1;
fa[v]=u;
dfs(v,edge[i].val);
if(sz[v]>sz[son[u]])son[u]=v;
sz[u]+=sz[v];
}
}
void build(int u,int ti)
{
int i,v;
w[u]=++id;top[u]=ti;vi[u]=1;
lis[id].i=id,lis[id].val=num[u];
if(son[u]) build(son[u],ti);
v=edge[i].v;
if(vi[v]||v==son[u]) continue;
build(v,v);
}
}
LL need(LL val,int u,int v)
{
int f1=top[u],f2=top[v];
cnt=0;
LL ans=0;
// cout<<u<<" "<<f1<<" "<<v<<" "<<f2<<" "<<w[f1]<<" "<<w[u]<<endl;
while(f1!=f2){
if(dep[f1]<dep[f2]){
swap(f1,f2),swap(u,v);
}
ans+=getans(w[f1],w[u],val,1);
u=fa[f1];f1=top[u];
}
if(dep[u]>dep[v])
swap(u,v);
if(u!=v)
ans+=getans(w[son[u]],w[v],val,1);
//cout<<u<<" "<<v<<" "<<val<<" "<<cnt<<" "<<ans<<" "<<val*cnt-ans<<endl;
ans=val*(LL)cnt-ans;
return ans;
}
void calc(int u,int v,LL k,LL a,LL b)
{
int x=u,y=v;
int f1=top[u],f2=top[v];
LL ans=10000000;
while(f1!=f2){
if(dep[f1]<dep[f2]){
swap(f1,f2),swap(u,v);
}
ans=min(ans,(LL)getmin(w[f1],w[u],1));
u=fa[f1];f1=top[u];
}
if(dep[u]>dep[v])
swap(u,v);
if(u!=v)
ans=min(ans,(LL)getmin(w[son[u]],w[v],1));
LL capacity=0;
if(k<min(a,b)){
printf("%I64d\n",ans);
return ;
}
if(a<=b){
printf("%I64d\n",k/a+ans);
return ;
}
if(k>=a)
capacity=(k-a)/b+1+ans;
LL l,r,mid,temp;
l=0,r=k/b+ans+1;
while(l+1<r){
mid=(l+r)>>1;
temp=need(mid,x,y);
temp*=b;
if(temp<=k)
l=mid;
else
r=mid-1;
}
if(r>=1)
if(need(r,x,y)*b<=k&&r>l)
l=r;
printf("%I64d\n",max(capacity,l));
return ;
}
int main()
{
int t,n,m,i,j,u,v,val,q,a,b,k,Case=0;
scanf("%d",&t);
while(t--){
init();
scanf("%d%d",&n,&m);
for(i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&val);
}
dfs(1,1200000000);
memset(vi,0,sizeof(vi));
build(1,1);
sort(lis+1,lis+id+1);
BuildTree(1,n,1);
for(i=1;i<=n;i++){
update(lis[i].i,lis[i].val,1);
}
printf("Case #%d:\n",++Case);
for(i=1;i<=m;i++){
scanf("%d%d%d%d%d",&u,&v,&k,&a,&b);
calc(u,v,k,a,b);
}
}
return 0;
}

posted @ 2013-09-16 23:27 fangguo 阅读(...) 评论(...) 编辑 收藏