UESTC_树上的距离 2015 UESTC Training for Graph Theory<Problem E>
E - 树上的距离
Time Limit: 2000/1000MS (Java/Others) Memory Limit: 262143/262143KB (Java/Others)
给你一棵带权树,边权表示两点间的距离。有如下两种操作:
- 询问两点间的最短距离。
- 修改一条边权值。
对每个操作1,回答两点间的距离。
Input
第一行一个数n,表示点的个数。接下来n−1行,每行3个数u,v,w,表示u,v间有权为w的边。边按照输入顺序从1到n−1编号。输入保证为一颗树。 (2≤n≤105,1≤u,v≤n,1≤w≤1000)
之后输入一个数q,表示询问个数。最后有q行,每行第一个数op(op=1或2)为操作类型。
当op=1时,输入u,v表示询问u,v间的距离。 (u≠v,1≤u,v≤n)
当op为2时,输入id,w表示把编号为id的边的权值改为w。 (1≤q≤105,1≤id≤n−1,1≤w≤1000)
Output
对于对每个操作1,输出一行,回答两点间的距离。
Sample input and output
Sample Input | Sample Output |
---|---|
5 |
5 |
解题报告:
这是一道 LCA + 欧拉序列 + 线段树题目
首先我们容易得出下列这个式子
设 distance(x) 为树上的点 x 到根的距离,设u为x,y的最近公共祖先
则distance of (x – y) = distance(x) + distance(y) – 2*distance(u)
那么我们该如何求得LCA呢
这里我采用的是tarjan离线处理所有询问.
一遍dfs处理所有询问的LCA,复杂度为O(n+q)
之后我们用一次dfs将树转为线性结构.
即记录这个点的入时间戳,也记录这个点的出时间戳.
容易得到[ 入时间戳 + 1 , 出时间戳 ] 恰好包含了这个点及其儿子
这样,本题就转换成了线段树区间更新 + 点查询的题目
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define pb push_back
using namespace std;
const int maxn = 2e5 + ; typedef struct Edge
{
int u,v,w;
Edge(int u,int v,int w)
{
this->u = u , this->v = v , this->w = w ;
}
}; typedef struct treenode
{
int l,r,lazy,sum;
void updata(int x)
{
lazy += x;
sum += (r-l+)*x;
}
}; typedef struct querynode
{
int type,t1,t2,lca;
}; typedef struct tarjan
{
int v , ansid;
tarjan(int v,int ansid)
{
this->v = v ,this->ansid = ansid;
}
}; treenode tree[maxn*]; void build_tree(int o,int l,int r)
{
tree[o].l = l , tree[o].r = r ; tree[o].sum = tree[o].lazy = ;
if (r > l)
{
int mid = l + (r-l)/;
build_tree(*o,l,mid);
build_tree(*o+,mid+,r);
}
} inline void push_up(int x)
{
tree[x].sum = tree[*x].sum + tree[*x+].sum;
} inline void push_down(int x)
{
int lazy = tree[x].lazy;
if (lazy)
tree[*x].updata(lazy),tree[*x+].updata(lazy);
tree[x].lazy = ;
} void updata(int ql,int qr,int o,int v)
{
int l = tree[o].l , r = tree[o].r;
if (ql <= l && qr >= r )
tree[o].updata(v);
else
{
int mid = l + (r-l)/;
push_down(o);
if (mid >= ql)
updata(ql,qr,*o,v);
if (mid < qr)
updata(ql,qr,*o+,v);
push_up(o);
}
} int querysum(int ql,int qr,int o)
{
int l = tree[o].l , r = tree[o].r;
if (ql <= l && qr >= r)
return tree[o].sum;
else
{
int mid = l + (r-l)/;
push_down(o);
int res = ;
if (mid >= ql)
res += querysum(ql,qr,*o);
if (mid < qr)
res += querysum(ql,qr,*o+);
push_up(o);
return res;
}
} int n,euler[maxn*],id[maxn][],sum[maxn*],deapth[maxn*],tot = ,pre[maxn],father[maxn];
vector<Edge>New_next[maxn],e;
bool vis[maxn];
querynode q[maxn];
vector<tarjan>use[maxn]; inline int find_set(int x)
{
return x != pre[x] ? pre[x] = find_set(pre[x]) : x;
} inline void union_set(int x,int y)
{
pre[find_set(x)] = y;
} void init_id(int cur)
{
id[cur][] = tot++;
for(int i = ; i < New_next[cur].size() ; ++ i)
{
int nextnode = New_next[cur][i].v;
if (nextnode == father[cur])
continue;
init_id(nextnode);
}
id[cur][] = tot++;
} void init_tarjan(int cur)
{
pre[cur] = cur;
vis[cur] = true;
for(int i = ; i < New_next[cur].size() ; ++ i)
{
int nextnode = New_next[cur][i].v;
if (nextnode == father[cur])
continue;
init_tarjan(nextnode);
union_set(nextnode,cur);
}
for(int i = ; i < use[cur].size() ; ++ i)
{
int v = use[cur][i].v , ansid = use[cur][i].ansid;
if (vis[v])
q[ansid].lca = find_set(v);
}
} void fatherset(int cur,int fat)
{
father[cur] = fat;
for(int i = ; i < New_next[cur].size() ; ++ i)
{
int nextnode = New_next[cur][i].v;
if (nextnode == fat)
continue;
fatherset(nextnode,cur);
}
} int main(int argc,char *argv[])
{
scanf("%d",&n);
memset(sum,,sizeof(sum));
memset(vis,false,sizeof(vis));
for(int i = ; i < n - ; ++ i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e.pb(Edge(u,v,w));
New_next[u].pb(Edge(u,v,w));
New_next[v].pb(Edge(v,u,w));
}
fatherset(,);
init_id();
build_tree(,,tot+);
for(int i = ; i < e.size() ; ++ i)
{
int u = e[i].u , v = e[i].v , w = e[i].w;
if (father[u] == v)
{
swap(u,v);
swap(e[i].u,e[i].v);
}
updata(id[v][]+,id[v][],,w);
}
int qnumber;
scanf("%d",&qnumber);
for(int i = ; i < qnumber ; ++ i)
{
int type,t1,t2;
scanf("%d%d%d",&type,&t1,&t2);
q[i].type = type,q[i].t1 = t1 , q[i].t2 = t2;
if (type & )
{
if (father[t1] == t2)
swap(q[i].t1,q[i].t2);
use[t1].pb(tarjan(t2,i));
use[t2].pb(tarjan(t1,i));
}
}
init_tarjan(); //离线处理
for(int i = ; i < qnumber ; ++ i)
{
int type = q[i].type ,t1 = q[i].t1 ,t2 = q[i].t2 ;
if (type & )
{
int lca = q[i].lca;
int p1 = querysum(id[t1][],id[t1][],);
int p2 = querysum(id[t2][],id[t2][],);
int p3 = querysum(id[lca][],id[lca][],);
printf("%d\n",p1+p2-*p3);
}
else
{
int u = e[t1-].u, v = e[t1-].v;
updata(id[v][]+,id[v][],, t2 - e[t1-].w);
e[t1-].w = t2;
}
}
return ;
}
UESTC_树上的距离 2015 UESTC Training for Graph Theory<Problem E>的更多相关文章
- UESTC_王之盛宴 2015 UESTC Training for Graph Theory<Problem K>
K - 王之盛宴 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- UESTC_方老师和农场 2015 UESTC Training for Graph Theory<Problem L>
L - 方老师和农场 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submi ...
- UESTC_秋实大哥带我飞 2015 UESTC Training for Graph Theory<Problem B>
B - 秋实大哥带我飞 Time Limit: 300/100MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- UESTC_小panpan学图论 2015 UESTC Training for Graph Theory<Problem J>
J - 小panpan学图论 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) S ...
- UESTC_排名表 2015 UESTC Training for Graph Theory<Problem I>
I - 排名表 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit S ...
- UESTC_韩爷的情书 2015 UESTC Training for Graph Theory<Problem H>
H - 韩爷的情书 Time Limit: 6000/2000MS (Java/Others) Memory Limit: 262144/262144KB (Java/Others) Subm ...
- UESTC_传输数据 2015 UESTC Training for Graph Theory<Problem F>
F - 传输数据 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- UESTC_邱老师的脑残粉 2015 UESTC Training for Graph Theory<Problem D>
D - 邱老师的脑残粉 Time Limit: 12000/4000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Sub ...
- UESTC_秋实大哥与时空漫游 2015 UESTC Training for Graph Theory<Problem C>
C - 秋实大哥与时空漫游 Time Limit: 4500/1500MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Su ...
随机推荐
- 【转】使用adb命令对手机进行截屏(截图)保存到电脑,SDCard
原文网址:http://blog.csdn.net/huangyabin001/article/details/29198367 adb shell /system/bin/screencap -p ...
- 2015第14周日WebSocket
清明时节雨纷纷,路上行人欲断魂,借问酒家何处是?牧童遥指杏花村.每次清明都不禁想起杜牧这首诗缅怀先人,此时第一句写时间天气,第二句写人物心情,第三句写解决方法,第四句给出解决方案,脍炙人口. 刚没事看 ...
- 【转】多核CPU运行模式
多核CPU运行模式主要有以下三种: •非对称多处理(Asymmetric multiprocessing,AMP)——每个CPU内核运行一个独立的操作系统或同一操作系统的独立实例(instantiat ...
- 创建UIButton
UIButtonCreate.h #import <UIKit/UIKit.h> @interface UIButtonCreate : UIButton /** * 创建UIButton ...
- PC--CSS常识
1.不要使用过小的图片做背景平铺.这就是为何很多人都不用 1px 的原因,这才知晓.宽高 1px 的图片平铺出一个宽高 200px 的区域,需要 200*200=40, 000 次,占用资源.2.无 ...
- 高仿拉手网底部菜单实现FragmentActivity+Fragment+RadioGroup
先把欢迎页和引导页的代码上传了http://download.csdn.net/detail/u013134391/7183787不要积分的. 底部菜单条实如今4.0曾经都是用tabhost.如今基本 ...
- 虚拟Linux 訪问win7共享文件夹方法
虚拟机訪问win7的共享文件夹 首先安装增强功能,这个不用多说 再者选择菜单中的设备->共享目录,设置为固定分配和自己主动挂载 在终端敲入命令df:发现有自己创建共享的文件夹 然后运行例如以下命 ...
- [Spring入门学习笔记][maven]
什么是maven? 我的理解: 一个项目有一大堆依赖包的时候,没必要下下来,可以利用maven中的pom.xml 指定需要那些依赖包,让maven去本地中央库(如果没找到)->网上仓库库帮你调用 ...
- java public protect default private
(1)对于public修饰符,它具有最大的访问权限,可以访问任何一个在CLASSPATH下的类.接口.异常等.它往往用于对外的情况,也就是对象或类对外的一种接口的形式. (2)对于protected修 ...
- json返回数据拼接HTML
<div class="box-lists"> </div> $.ajax({ url: 'AjaxPage/AjaxHandler.ashx', typ ...