题目链接:

http://codeforces.com/gym/101161/attachments

题意:

给出节点数为$n$的树

有$q$次询问,输出$a$节点到$b$节点路程中,经过的边的中位数

数据范围:

$1\leq n \leq 100000$

$1\leq q \leq 100000$

分析:

建一颗主席树,不同的是,节点的根继承的是父节点的根

再用$lca$求出公共祖先$tree[a]+tree[b]-2*tree[lca(a,b)]$

ac代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 5e4+100;
struct Node{
int L,R,num;
}tree[maxn*20];
int dep[maxn],fa[maxn][20],n,cnt;
int root[maxn],vis[maxn];
vector<pii>ve[maxn]; void update(int x,int&root,int st,int en){
tree[++cnt]=tree[root];
root=cnt;
tree[root].num++;
if(st==en)return ;
int md=(st+en)/2;
if(x<=md)
update(x,tree[root].L,st,md);
else
update(x,tree[root].R,md+1,en);
} void dfs(int x,int fx,int w){
if(vis[x])return ;
vis[x]=1;
root[x]=root[fx];
if(x!=1)update(w,root[x],1,1e5);
dep[x]=dep[fx]+1;
fa[x][0]=fx;
for(int i=1;(1<<i)<dep[x];i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=0;i<ve[x].size();i++)
dfs(ve[x][i].first,x,ve[x][i].second);
}
int lca(int a,int b){
if(dep[a]>dep[b])swap(a,b);
for(int i=19;i>=0;i--)
if(dep[fa[b][i]]>=dep[a])b=fa[b][i];
if(a==b)return a;
for(int i=19;i>=0;i--)
if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
return fa[a][0];
} int quer(int a,int b,int c,int st,int en,int k){
if(st==en)return st;
int dd=tree[tree[a].L].num+tree[tree[b].L].num-2*tree[tree[c].L].num;
//cout<<dd<<" "<<k<<endl;
int md=(st+en)/2;
if(dd>=k)return quer(tree[a].L,tree[b].L,tree[c].L,st,md,k);
return quer(tree[a].R,tree[b].R,tree[c].R,md+1,en,k-dd);
}
int main()
{
int T,q;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
cnt=0;
for(int i=1;i<=n;i++){
ve[i].clear();
vis[i]=0;
for(int j=0;j<20;j++)
fa[i][j]=0;
}
for(int i=1;i<=n-1;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
ve[a].push_back(make_pair(b,c));
ve[b].push_back(make_pair(a,c));
} dfs(1,0,-1);
//cout<<fa[6][2]<<endl;
scanf("%d",&q);
while(q--){
int a,b,c;
scanf("%d %d",&a,&b);
c=lca(a,b);
int len=dep[a]+dep[b]-2*dep[c];
//cout<<c<<" "<<len<<endl;
if(len%2==0){
int ans1=quer(root[a],root[b],root[c],1,1e5,len/2);
int ans2=quer(root[a],root[b],root[c],1,1e5,len/2+1);
printf("%d",(ans1+ans2)/2);
if((ans1+ans2)%2)printf(".5");
else printf(".0");
}
else
printf("%d.0",quer(root[a],root[b],root[c],1,1e5,len/2+1));
printf("\n");
}
}
return 0;
}

  

最新文章

  1. Eclipse更新SDK速度慢,解决办法
  2. html初始化页面和a标签无下划线
  3. (转) Active Record
  4. c#对Aspose.Word替换书签内容的简单封装
  5. BZOJ 3752 世界树
  6. jsb游戏闪退 ScriptingScore::executeFunctionWithOwner 出错
  7. supervisor运行golang守护进程
  8. [Ruby on Rails系列]6、一个简单的暗语生成器与解释器(上)
  9. freeCodeCamp:GO BYBY GO!
  10. CSS之拖拽库2
  11. Codeforces Round #319 (Div. 1) C. Points on Plane 分块
  12. WordPress SEO ☞ WordPress网站终极优化指南
  13. VS2008一个小bug
  14. ubuntu linux 13.04更新
  15. The type or namespace name &#39;****&#39; could not be found
  16. 下拉菜单被挡住了,DIV置于最底层的方法
  17. Python 学习笔记7 条件语句 If
  18. GPIO8种方式小总结
  19. dva.js 上手
  20. hdu 6385

热门文章

  1. sql注入测试(2)---实例测试
  2. (二十六)JavaBean
  3. 微信小微商户申请入驻 .NET C#实现微信小微商户进件API
  4. vue+scss动态改变主题颜色
  5. C++线程同步之原子操作
  6. ajax格式,转入后台
  7. ionic 局部刷新
  8. Image Processing and Analysis_8_Edge Detection:Local Scale Control for Edge Detection and Blur Estimation——1998
  9. 线段树lazy模板 luogu3372
  10. c#系统预定义类型