Description

Input

Output

Sample Input

5 3
1 2 3
1 3 1
2 4 4
2 5 2
1 2
3 3
5 1

Sample Output

3
6
2

Data Constraint

Solution

  • 这题用到点分树,即点分治时重心(前面的连向后面的)建成的树。

  • 在每个点上记录一个数组 fff,保存该点子树里的点到其距离(原树,包括自己),并排好序。

  • 询问要二分答案 kkk ,并判断有多少个点的距离 ≤k\leq k≤k 即可。

  • 那么询问时从该点开始往点分树的父亲上走,每次加上符合的个数(在数组 fff 里二分即可)。

  • 但是这样会算重,即从点分树父亲那儿走到自己的答案可能算重了,我们需要减去一些。

  • 于是再开一个数组 ggg ,记录一个点子树里(原树,包括自己)到其点分树父亲的距离。

  • 在排好序的数组 ggg 里二分算重的个数并减去即可。

  • 询问时二分答案、在点分树上往父亲跳、在数组里二分计算的复杂度均为 O(logn)O(log\ n)O(log n) 。

  • 总时间复杂度为 O(nlog⁡3n)O(n\log^3n)O(nlog3n) 。

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cctype>
using namespace std;
const int N=5e4+5;
int n,tot,node,mx,dep,dis,siz;
int first[N],nex[N<<1],en[N<<1],w[N<<1];
int first1[N],nex1[N],en1[N];
int fa[N],f[N],size[N],h[N][16],len[N][16],deep[N],dp[N],pre[N][20];
bool bz[N];
vector<int>g[N],d[N];
inline int read()
{int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X;
}
void write(int x)
{if(x>9) write(x/10);putchar(x%10+'0');
}
inline int max(int x,int y)
{return x>y?x:y;
}
inline void insert(int x,int y,int z)
{nex[++tot]=first[x];first[x]=tot;en[tot]=y;w[tot]=z;
}
inline void insert1(int x,int y)
{nex1[++tot]=first1[x];first1[x]=tot;en1[tot]=y;
}
void find(int x,int y,int z)
{size[x]=1;f[x]=0;for(int i=first[x];i;i=nex[i])if(en[i]^y && !bz[en[i]]){find(en[i],x,z+w[i]);size[x]+=size[en[i]];f[x]=max(f[x],size[en[i]]);}f[x]=max(f[x],siz-size[x]);if(f[x]<mx) mx=f[node=x],dep=z;
}
void down(int x,int y,int rt,int z)
{g[rt].push_back(z);for(int i=first[x];i;i=nex[i])if(en[i]^y && !bz[en[i]]) down(en[i],x,rt,z+w[i]);
}
void dfs(int x,int y)
{bz[x]=true;if(fa[x]=y) insert1(y,x);int siz1=siz;for(int i=first[x];i;i=nex[i])if(!bz[en[i]]){if(size[x]<size[en[i]]) siz=siz1-size[x]; else siz=size[en[i]];mx=siz;find(en[i],x,w[i]);down(node,0,node,0);dfs(node,x);}
}
void get(int x,int y,int z)
{if(z>dis) dis=z,node=x;for(int i=first[x];i;i=nex[i])if(en[i]^y){if(en[i]>1 && !h[en[i]][0]){h[en[i]][0]=x;len[en[i]][0]=w[i];deep[en[i]]=deep[x]+1;}get(en[i],x,z+w[i]);}
}
inline int calc(int x,int y)
{if(deep[x]<deep[y]) swap(x,y);int s=0;for(int i=log2(deep[x]);i>=0;i--)if(deep[h[x][i]]>=deep[y]){s+=len[x][i];x=h[x][i];}if(x==y) return s;for(int i=log2(deep[x]);i>=0;i--)if(h[x][i]^h[y][i]){s+=len[x][i]+len[y][i];x=h[x][i];y=h[y][i];}s+=len[x][0]+len[y][0];return s;
}
void dg(int x)
{dp[x]=dp[fa[x]]+1;for(int y=fa[x],l=x;y;l=y,y=fa[y]){int z=calc(x,y);pre[x][dp[y]]=z;if(l) d[l].push_back(z);}for(int i=first1[x];i;i=nex1[i])if(en1[i]^fa[x]) dg(en1[i]);
}
int main()
{freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);n=read();int m=read();for(int i=1;i<n;i++){int x=read(),y=read(),z=read();insert(x,y,z);insert(y,x,z);}get(deep[1]=1,0,0);get(node,0,0);for(int j=1;j<16;j++)for(int i=1;i<=n;i++){h[i][j]=h[h[i][j-1]][j-1];len[i][j]=len[i][j-1]+len[h[i][j-1]][j-1];}tot=0;mx=siz=n;find(1,0,0);down(node,0,node,0);dfs(node,0);for(int i=1;i<=n;i++)if(!fa[i]){node=i;break;}dg(node);for(int i=1;i<=n;i++) g[i].push_back(dis);for(int i=1;i<=n;i++) sort(g[i].begin(),g[i].end());for(int i=1;i<=n;i++) d[i].push_back(dis);for(int i=1;i<=n;i++) sort(d[i].begin(),d[i].end());/*for(int j=1;j<=n;j++,putchar('\n'))for(int i=0;i<(int)g[j].size();i++) printf("%d ",g[j][i]);*/while(m--){int u=read(),k=read()+1;int l=1,r=dis,ans=0;while(l<=r){int mid=l+r>>1;int sum=upper_bound(g[u].begin(),g[u].end(),mid)-g[u].begin();for(int x=u;x^node;x=fa[x]){int lim=pre[u][dp[fa[x]]];if(lim>mid) continue;sum+=upper_bound(g[fa[x]].begin(),g[fa[x]].end(),mid-lim)-g[fa[x]].begin();sum-=upper_bound(d[x].begin(),d[x].end(),mid-lim)-d[x].begin();}if(sum>=k){ans=mid;r=mid-1;}else l=mid+1;}write(ans),putchar('\n');}return 0;
}

JZOJ 5898. 【NOIP2018模拟10.6】距离统计相关推荐

  1. [JZOJ 5911] [NOIP2018模拟10.18] Travel 解题报告 (期望+树形DP)

    题目链接: http://172.16.0.132/senior/#contest/show/2530/1 题目: EZ同学家里非常富有,但又极其的谦虚,说话又好听,是个不可多得的人才.       ...

  2. [JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)

    题目链接: https://jzoj.net/senior/#contest/show/2529/2 题目: 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城 ...

  3. jzoj 5906. 【NOIP2018模拟10.15】传送门(树形dp)

    5906. [NOIP2018模拟10.15]传送门 Description 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normal ...

  4. jzoj5904. 【NOIP2018模拟10.15】刺客信条(并查集)

    5904. [NOIP2018模拟10.15]刺客信条 Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一 ...

  5. jzoj5920. 【NOIP2018模拟10.21】风筝(dp,最长上升子序列)

    5920. [NOIP2018模拟10.21]风筝 Description 当一阵风吹来,风筝飞上天空,为了你,而祈祷,而祝福,而感动-- Description oyiya 在 AK 了 IOI 之 ...

  6. JZOJ 5930. 【NOIP2018模拟10.26】山花

    Description 3.1 Background 春日的山中灌木茂盛,几乎长到了人的腰间,将山间都铺满了绿色.雨后的灌木之间还带着晨露,总会沾湿走过的行人的衣裳. 林中枝叶茂密,不过树木长的并不紧 ...

  7. JZOJ 5939. 【NOIP2018模拟10.30】阻击计划

    Description 最近,小J发现小R和小Z之间的关系十分密切,心中十分嫉妒,为了拆散他们,小J经常扰乱他们一起玩耍的计划. 问题描述 小R和小Z打算在这个周末一起骑车在G国的城市看风景,G国的城 ...

  8. JZOJ 5932. 【NOIP2018模拟10.27】情报中心

    Description 题目背景 .飞纷火战来年近国 D 和国 C .飞乱子鸽来年近国 D 和国 C 题面描述 最近,C 国成功地渗透进入了 D 国的一个城市.这个城市可以抽象成一张有 n 个节点,节 ...

  9. JZOJ 5904. 【NOIP2018模拟10.15】刺客信条(AC)

    Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一名刺客.最终,凭借着他的努力和出众的天赋,成为了杰出的刺 ...

最新文章

  1. 10 Windows编程——鼠标消息
  2. django rest-framework 1.序列化 一
  3. Cocos2d-x的坐标系统
  4. 深挖BAT内部级别和薪资待遇
  5. PKUSC2019游记
  6. jsp中获取不到后台请求域中的值
  7. boost::hana::test::TestLogical用法的测试程序
  8. 《学习OpenCV》课后习题解答1
  9. base昆明,腾讯云在合作伙伴的阵营中@了TA
  10. 利用idea构建hibernate
  11. Microsoft.mshtml.dll 添加引用及类型选择错误问题解决办法
  12. 基于CANape开发的XCP测量
  13. matlab模拟小球碰撞,在MATLAB中实现模拟小球上抛和反弹运动
  14. 汉王OCR6.0软件使用分享
  15. 2021年华为OD面试流程
  16. 深入解读HTTP3的原理及应用
  17. 设计心理学2-与复杂共处【读书笔记】
  18. 光伏电站智慧运维辅助系统解决方案 助力光伏运维监控智能化
  19. codeblock的c语言编译,CodeBlocks无法编译的原因和解决办法
  20. c语言表达ch是大写英文字母,做几道C语言的习题!

热门文章

  1. 【项目实践】【01】发货管理系统 SPS (2007年12月23日更新)
  2. 正则表达式匹配C++代码实现
  3. Python学习:深入Python流程控制
  4. /etc/ld.so.conf.d/目录下文件的作用
  5. [云炬创业基础笔记]第十章企业的利润计划测试6
  6. 科大星云诗社动态20210823
  7. [云炬python3玩转机器学习笔记] 3-3Numpy数据基础
  8. 952计算机网络是那本书,952计算机网络复习参考提纲.doc
  9. 别人写好的爬虫怎么运行_怎么写好楷书?
  10. go语言中的defer