csu 1798(树上最远点对,线段树+lca)
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)的更多相关文章
- 51 nod 1766 树上的最远点对(线段树+lca)
1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个 ...
- 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 ...
- HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)
layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...
- 51nod 1766 树上的最远点对——线段树
n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j& ...
- BZOJ 1798: [Ahoi2009]Seq 维护序列seq( 线段树 )
线段树.. 打个 mul , add 的标记就好了.. 这个速度好像还挺快的...( 相比我其他代码 = = ) 好像是#35.. ---------------------------------- ...
- [Vani有约会]雨天的尾巴——树上差分+动态开点线段树合并
题目描述 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮. 然后深绘里想知道,当所 ...
- bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeO ...
- 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...
- CSU 2151 集训难度【多标记线段树】
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2151 Input 第一行三个数n,m,v0 表示有n名萌新和m次调整,初始时全部萌新的集训难度 ...
随机推荐
- 【读书笔记】《HTTP权威指南》:Web Robots
一.概述 Web机器人(Web Robots)是一种Web客户端的软件程序,它自动发起一系列的Web事务,从而在没有人工参与的状态下完成各种Web数据的搜集和处理. 典型的Web机器人有: 股票绘图机 ...
- PHP 中的新语法 new static 是个啥意思?
简单通俗的来说, self就是写在哪个类里面, 实际调用的就是这个类.所谓的后期静态绑定, static代表使用的这个类, 就是你在父类里写的static, 然后通过子类直接/间接用到了这个stati ...
- 复习JavaScript随手记
数据类型 基本类型 string number boolean undefined number类型,包含整数浮点数 NaN和自己都不相等,涉及NaN的计算结果都是NaN isNaN()函数用于判断一 ...
- 最近遇到的DISCUZ一些问题解决方法
“抱歉,您的请求来路不正确或表单验证串不符,无法提交” 打开“source\class\helper\helper_form.php”, 然后把“$_GET[‘formhash’] == formha ...
- iOS之富文本(一)
NSAttributedString叫做富文本,是一种带有属性的字符串,通过它可以轻松的在一个字符串中表现出多种字体.字号.字体大小等各不相同的风格,还可以对段落进行格式化. 通过以下代码即可实现上面 ...
- js 判断图片是否加载完成(使用 onload 事件)
我们在写 jquery 的时候一般都会写 $(document).ready,加载完成事件还有一个就是 onload onload 与 ready 的区别是: 1.ready 是 DOM 加载完成的事 ...
- python学习笔记(六) 函数式编程
一 函数对象 函数同样可以作为对象复制给一个变量,如下: f = abs; print(f(-10)) f = 'abs'; print(f) def add(a,b,f): return f(a) ...
- 手脱nSPack 2.1 - 2.5
1.载入PEID 使用核心扫描出的结果 nSPack 2.1 - 2.5 -> North Star/Liu Xing Ping 2.载入OD,一进来就是一个大跳转,F8跟着走 >- E9 ...
- [转]hadoop2.x常用端口
原文地址:http://www.zhixing123.cn/ubuntu/40649.html HDFS DataNode 50010 dfs.datanode.address datanode服务端 ...
- .Net各版本新特性
序言 C# 1.0 (2002) public interface IDateProvider { DateTime GetDate(); } 隐式接口实现 public class DefaultD ...