首先答案一定是包含直径某个端点的一个连通块里所有边权值之和,设直径为$AB$,以$A$和$B$分别为根进行处理。

首先按照最长路法则将这棵树进行树链剖分,那么每个叶子的贡献为它与它所在链顶端的点的距离。

将叶子按贡献从大到小排序,并求出$h[x]$表示$x$子树内叶子排名的最小值。

对于询问$(x,k)$,需要取$2k-1$个叶子。

如果$h[x]\leq k$,那么说明前$2k-1$个叶子形成的连通块经过了$x$点,直接返回前$2k-1$个叶子的贡献和即可。

否则对于一个选中的叶子$y$,如果它顶端不是$x$的祖先,那么踢掉$y$的代价为$y$的贡献。

否则踢掉$y$的代价为$y$到$lca(x,y)$的距离。

那么对于最优情况,要么踢掉第$2k-1$大的叶子,要么踢掉第二种情况里深度最大的叶子$y$。找到这个$y$可以通过轻重链剖分+二分查找得到。

总时间复杂度为$O((n+m)\log n)$。

#include<cstdio>
#include<algorithm>
#define N 100010
using namespace std;
int n,m,i,x,y,z,g[N],v[N<<1],w[N<<1],nxt[N<<1],ed,d[N],val[N],A,B;
inline bool cmp(int x,int y){return val[x]>val[y];}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x,int y){
if(d[x]>=d[z])z=x;
for(int i=g[x];i;i=nxt[i])if(v[i]!=y)d[v[i]]=d[x]+w[i],dfs(v[i],x);
}
struct DS{
int s[N],f[N],d[N],son[N],top[N],m,q[N],sum[N],h[N];
int size[N],SON[N],TOP[N],dfn,loc[N],seq[N];
void dfs(int x){
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
s[v[i]]=s[x]+w[i],f[v[i]]=x,dfs(v[i]);
if(d[v[i]]+w[i]>=d[x])d[x]=d[son[x]=v[i]]+w[i];
}
}
void dfs2(int x,int y){
top[x]=y;val[x]=s[x]-s[y];
if(!son[x]){q[++m]=x;return;}
dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]&&v[i]!=son[x])dfs2(v[i],x);
}
void dfs3(int x){
if(!h[x])h[x]=m;
size[x]=1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
dfs3(v[i]),h[x]=min(h[x],h[v[i]]),size[x]+=size[v[i]];
if(size[v[i]]>size[SON[x]])SON[x]=v[i];
}
}
void dfs4(int x,int y){
TOP[x]=y;seq[loc[x]=++dfn]=x;
if(SON[x])dfs4(SON[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]&&v[i]!=SON[x])dfs4(v[i],v[i]);
}
void init(int S){
dfs(S),dfs2(S,S);
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++)h[q[i]]=i,sum[i]=sum[i-1]+val[q[i]];
dfs3(S),dfs4(S,S);
}
inline int ask(int l,int r,int k){
int t,mid;
while(l<=r)if(h[seq[mid=(l+r)>>1]]<=k)l=(t=mid)+1;else r=mid-1;
return seq[t];
}
inline int lca(int x,int k){for(;x;x=f[TOP[x]])if(h[TOP[x]]<=k)return ask(loc[TOP[x]],loc[x],k);}
inline int query(int x,int k){
k=k*2-1;
if(k>=m)return sum[m];
if(h[x]<=k)return sum[k];
int y=lca(x,k);
return sum[k]+s[q[h[x]]]-s[y]-min(s[q[k]]-s[top[q[k]]],s[q[h[y]]]-s[y]);
}
}DA,DB;
int main(){
read(n),read(m);
for(i=1;i<n;i++)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
dfs(1,z=0);A=z;
for(i=1;i<=n;i++)d[i]=0;
dfs(A,z=0);B=z;
DA.init(A),DB.init(B);
while(m--)read(x),read(y),printf("%d\n",max(DA.query(x,y),DB.query(x,y)));
return 0;
}

  

BZOJ3607 : 数据网络的更多相关文章

  1. 转:Android 判断用户2G/3G/4G移动数据网络

    Android 判断用户2G/3G/4G移动数据网络 在做 Android App 的时候,为了给用户省流量,为了不激起用户的愤怒,为了更好的用户体验,是需要根据用户当前网络情况来做一些调整的,也可以 ...

  2. Android 判断用户2G/3G/4G移动数据网络

    Android 判断用户2G/3G/4G移动数据网络 在做 Android App 的时候,为了给用户省流量,为了不激起用户的愤怒,为了更好的用户体验,是需要根据用户当前网络情况来做一些调整的,也可以 ...

  3. Python数据网络采集5--处理Javascript和重定向

    Python数据网络采集5--处理Javascript和重定向 到目前为止,我们和网站服务器通信的唯一方式,就是发出HTTP请求获取页面.有些网页,我们不需要单独请求,就可以和网络服务器交互(收发信息 ...

  4. jq easyui数据网络的分页过程

    第一次写技术方面的文章,有点忐忑,总怕自己讲的不对误导别人.但是万事总有个开头,有不足错误之处,请各位读者老爷指出. 言归正传,最近刚进新公司,上头要求我先熟悉熟悉easyui这个组件库.在涉及到da ...

  5. (转)Android 判断用户2G/3G/4G移动数据网络

    在做 Android App 的时候,为了给用户省流量,为了不激起用户的愤怒,为了更好的用户体验,是需(要根据用户当前网络情况来做一些调整的,也可以在 App 的设置模块里,让用户自己选择,在 2G ...

  6. 通行导论-IP数据网络基础(2)

    传输控制协议(TCP) 差错控制:TCP使用差错控制提供可靠性,包括检测受到损伤.丢失.失序的报文段 实现方法:1.16位检验和,2.确认机制:采用确认证实收到的报文段,3.重传(设置一个重传超时RT ...

  7. 通信导论-IP数据网络基础(1)

    TCP/IP封装过程: 端口号:服务器一般都是通过知名端口号(1~1023)来识别应用程序,(TCP)21.23.25,(UDP)53.69.161 TCP报文格式: 字节号:TCP把连接中发送的所有 ...

  8. 通信导论-IP数据网络基础(4)

    IP地址的编址方法--IP地址+掩码地址=网络地址 分类的IP地址 每一类地址都由两个固定长度的字段组成,其中一个字段是网络号 net-id,标志主机或路由器所连接到的网络,另一个字段则是主机号 ho ...

  9. 通信导论-IP数据网络基础(3)

    ICMP(IP辅助协议)--网际控制报文协议 ICMP报文种类:ICMP差错报文(终点不可达.时间超过等5种)和ICMP询问报文(回送请求和回答请求.时间戳请求和回答报文2种) ICMP是一种集差错报 ...

随机推荐

  1. java web统计当前访问用户数量

    1.使用SessionListener监听器,监听创建与销毁session的操作,利用计数方式记录当前session的数量

  2. hdu1722(gcd)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1722 题意:要使一块蛋糕既能均分给a个人,又能均分给b个人,问至少需要分成几块(不需要每块都一样大小) ...

  3. NYOJ926(概率)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=926 设最终A获胜的概率为P,则B获胜的概率为1-P: 因此我们只需要考虑A获胜的概率即可 ...

  4. 20145206实验四《Android开发基础》

    20145206 实验四<Android开发基础> 实验内容 ·安装Android Studio ·运行安卓AVD模拟器 ·使用安卓运行出虚拟手机并显示HelloWorld以及自己的学号 ...

  5. Pyqt 窗体间传值

    窗体间传值网上有好多方法,比如新建文件,先将子类窗体的数据传到文件中,父窗体读取文件.  Signal&Slot机制进行传值 等等 在这里,我们就举个采用apply方法:Signal& ...

  6. OCJP(1Z0-851) 模拟题分析(七)-->214

    Exam : 1Z0-851 Java Standard Edition 6 Programmer Certified Professional Exam 以下分析全都是我自己分析或者参考网上的,定有 ...

  7. mac liteIDE调试配置

    http://studygolang.com/articles/1636 brew install https://raw.github.com/Homebrew/homebrew-dupes/mas ...

  8. Oracle 备份与恢复介绍

    一.Oracle备份方式分类:Oracle有两类备份方式:(1)物理备份:是将实际组成数据库的操作系统文件从一处拷贝到另一处的备份过程,通常是从磁盘到磁带.物理备份又分为冷备份.热备份:   (2)逻 ...

  9. C# 实现单实例程序

    在我们经常使用的软件中,当我们已经打开后,再次打开时,有的软件不会出现两个.例如有道词典,会将上次的界面显示出来,或者提示我们“该程序已经运行...”.我通过一个简单的C# WPF例子来说明. 首先我 ...

  10. FrameLayout

    FrameLayout是最简单的布局了. ① 所有放在布局里的控件,都按照层次堆叠在屏幕的左上角.后加进来的控件覆盖前面的控件. ② 该布局container可以用来占有屏幕的某块区域来显示单一的对象