1798: 小Z的城市

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 60  Solved: 16
[Submit][Status][Web Board]

Description

小Z身为A国的君王,A国的所有城市都归小A所有,A国中从任意一个城市出发都能到达其他任意一个城市,每两个直接相邻的城市xi , yi之间都有一条已知长度的路径相连。A国共有n个城市(编号为1~n),被n-1条无向边相连。小Y和小X的开国功臣,但是小X擅文,小Y好武,所以他们关系很差,现在小Z想在区间[l ,r]的城市中选择两个奖赏这两位开国功臣一人一个城市,彼此厌恶的小X和小Y想让聪明的你飞到A国帮助他们做出选择可以距离彼此更远。

(也就是说最后小X会选择城市idx(l<=idx<=r) , 小Y会选择城市idy(l<=idy<=r) , 保证idx!=idy 而且idx距离idy尽可能远)。

Input

多组数据

每组数据第一行两个正整数n和q 表示A国有n个城市,q次询问 ( 2<=n <=100000 , q<=100000 )

接下来n-1行,每行输入3个正整数xi , yi , di 表示城市xi与yi被一条长度为di的路径相连

(1<=xi , yi<=n , di<=100)

接下来q个询问,每次询问输入一行li和ri,对于每次询问希望在li和ri区间选择两个城市分给小X和小Y,使他们距离最大 (1<=li < ri<=n)

所有数据保证Σn <=500000

Output

每次询问输出一个使小X和小Y距离的最大值

Sample Input

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

Sample Output

10

题解:线段树+lca .. 首先要知道一个这样的东西,假如一棵子树 A和另外一棵子树 B合并成 C,那么C 里面的最远点对是原来的A树里面最远点对和B树里面的最远点对这四个点中间的 2 个.所以知道了这个特性

所有的点下面的子树的最远点对就可以利用线段树进行维护了,树上最远的两个点之间的距离是 dis[u]+dis[v]-2*dis[lca(u,v)]
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef vector<int> vi;
const int N = ;
const int DEG = ;
int n,q;
struct Edge
{
int v,w,next;
} edge[N];
int head[N],tot,cost[N];
void addEdge(int u,int v,int w)
{
edge[tot].v = v,edge[tot].w = w,edge[tot].next = head[u],head[u] = tot++;
}
void init()
{
memset(head,-,sizeof(head));
tot = ;
}
/************* lca 调用 dfs(1,0,0) 以及 getanc() ***************/
int anc[N][DEG],dep[N];
void dfs(int u,int fa,int d,int w)
{
dep[u]=d;
anc[u][]=fa;
cost[u] = w;
for (int i=head[u]; i!=-; i=edge[i].next)
if (edge[i].v!=fa) dfs(edge[i].v,u,d+,w+edge[i].w);
} void getanc()
{
for (int i=; i<DEG; i++)
for (int j=; j<=n; j++)
anc[j][i]=anc[anc[j][i-]][i-];
} int swim(int u,int H)
{
int i=;
while (H)
{
if (H&) u=anc[u][i];
i++;
H>>=;
}
return u;
} int lca(int u,int v)
{
if (dep[u]<dep[v]) swap(u,v);
u=swim(u,dep[u]-dep[v]);
if (u==v) return u;
for (int i=DEG-; i>=; i--)
{
if (anc[u][i]!=anc[v][i])
{
u=anc[u][i];
v=anc[v][i];
}
}
return anc[u][];
}
/************ segment tree *****************/
int getdistance(int a,int b)
{
int _lca = lca(a,b);
return cost[a]+cost[b]-*cost[_lca];
}
vi tree[N<<]; /// tree[i] 管辖的是以 i 为根节点的子树中相聚最远的两点
vi max_dis_point(vi a,vi b)
{
for(int i=; i<b.size(); i++)
{
a.push_back(b[i]);
}
vi ans;
int _max = -;
for(int i=; i<a.size(); i++)
{
for(int j=i+; j<a.size(); j++)
{
int _distance = getdistance(a[i],a[j]);
if(_distance>_max)
{
_max = _distance;
ans.clear();
ans.push_back(a[i]);
ans.push_back(a[j]);
}
}
}
return ans;
}
void build(int l,int r,int idx)
{
if(l==r)
{
tree[idx].push_back(l);
tree[idx].push_back(l);
return;
}
int mid = (l+r)>>;
build(l,mid,idx<<);
build(mid+,r,idx<<|);
tree[idx] = max_dis_point(tree[idx<<],tree[idx<<|]);
}
vi query(int l,int r,int L,int R,int idx)
{
vi ans;
ans.clear();
if (r < L || R < l) return ans;
if(l >= L&& r <= R)
{
return tree[idx];
}
else
{
vi vl,vr;
int mid = (l+r)>>;
vl = query(l,mid,L,R,idx<<);
vr = query(mid+,r,L,R,idx<<|);
return max_dis_point(vl,vr);
} }
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
init();
for(int i=; i<=*n; i++) tree[i].clear();
for(int i=; i<n; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
addEdge(v,u,w);
}
dfs(,,,);
getanc();
build(,n,);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
vi ans = query(,n,a,b,);
int res = ;
if(ans.size()==)
{
res = getdistance(ans[],ans[]);
}
else res = getdistance(ans[],ans[]);
printf("%d\n",res);
}
}
return ;
}

csu 1798(树上最远点对,线段树+lca)的更多相关文章

  1. 51 nod 1766 树上的最远点对(线段树+lca)

    1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题   n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个 ...

  2. BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 9280  Solved: 2421 ...

  3. HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)

    layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...

  4. 51nod 1766 树上的最远点对——线段树

    n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j& ...

  5. BZOJ 1798: [Ahoi2009]Seq 维护序列seq( 线段树 )

    线段树.. 打个 mul , add 的标记就好了.. 这个速度好像还挺快的...( 相比我其他代码 = = ) 好像是#35.. ---------------------------------- ...

  6. [Vani有约会]雨天的尾巴——树上差分+动态开点线段树合并

    题目描述 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所 ...

  7. bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeO ...

  8. 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)

    P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...

  9. CSU 2151 集训难度【多标记线段树】

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2151 Input 第一行三个数n,m,v0 表示有n名萌新和m次调整,初始时全部萌新的集训难度 ...

随机推荐

  1. Hive(五)hive的高级应用

    一.视图 视图:享用基本表的数据,不会生成另外一份数据创建视图:create view view_name as select * from carss;create view carss_view ...

  2. dorado事件

    //----------------------------------------------------------------------------// //校验实体数据是否填写if(enti ...

  3. powerdesigner中物理模型与sql脚本的以及与数据库的连接设置

    使用JDBC连接失败的解决方案: http://blog.csdn.net/t37240/article/details/51595097 使用powerdesigner工具我们可以方便的根据需求分析 ...

  4. C++ string的那些坑

    1. size_type find_first_of( const basic_string &str, size_type index = 0 ); 查找在字符串中第一个与str中的某个字符 ...

  5. UVA 818 Cutting Chains

    https://vjudge.net/problem/UVA-818 题意: 有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链 n<=15 因为n< ...

  6. 30款基于 jQuery & CSS3 的加载动画和进度条插件

    我们所生活每一天看到的新技术或新设计潮流的兴起,Web 开发正处在上升的时代.HTML5 & CSS3 技术的发展让 Web 端可以实现的功能越来越强大. 加载动画和进度条使网站更具吸引力.该 ...

  7. 【CodeForces】713 C. Sonya and Problem Wihtout a Legend

    [题目]C. Sonya and Problem Wihtout a Legend [题意]给定n个数字,每次操作可以对一个数字±1,求最少操作次数使数列递增.n<=10^5. [算法]动态规划 ...

  8. Docker 配置国内镜像拉取中心,Configure docker to use faster registries in China.

    Networking in China is really bad when it comes to using some cloud based tools like docker, it's us ...

  9. 【BZOJ 1001】[BJOI2006]狼抓兔子(最大流)

    题目链接 最大流裸题,没什么好说吧,恰好点数多,考验网络流的效率,正好练\(Dinic\). #include <cstdio> #include <queue> #inclu ...

  10. c++刷题(3/100)数独,栈和队列

    stack的基本操作 • s.size():返回栈中的元素数量 • s.empty():判断栈是否为空,返回true或false • s.push(元素):返回对栈顶部“元素”的可变(可修改)引用 • ...