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 ...
随机推荐
- 单目录下多文件 makefile编写
makefile很久就接触过了,但是一直没怎么深入的去学习和总结:在项目中我也只是看看makefile或者修改部分语句,全部自己动手写的话还真没有:知识在于沉淀,这句说的非常好,所以现在把自己理解的东 ...
- C#开发者准备的通用性代码审查清单
这是为C#开发者准备的通用性代码审查清单,可以当做开发过程中的参考.这是为了确保在编码过程中,大部分通用编码指导原则都能注意到.对于新手和缺乏经验(0到3年工作经验)的开发者,参考这份清单编码会很帮助 ...
- 软硬结合的可穿戴式app
可穿戴设备已经非常的火热了,各种手环.手表之类的硬件设备已经层出不穷,并且功能也已经越发强大,从简单的运动.心率追踪,到现在的血糖.心电图监测,“量化自我”的愿景似乎已经变得越来越明朗,但也正是在这样 ...
- 自定义ScrollViewer的Touch事件--触摸上下移动ScrollViewer滚动到指定位置
double mPointY;//触摸点的Y坐标 double mOffsetY;//滚动条当前位置 bool mIsTouch = false;//是否触摸 //触摸事件 private void ...
- java中File类的相关学习
File类 1.关于系统路径分割符. 在Windows中,使用反斜杠“\”作为路径分割符,比如“c:\test”,但是java中反斜杠表示转义,所以需要用“C:\\test”在程序中来表示路径.还可以 ...
- 【转】DM8168图像处理Link
1> dei dei 主要做数据交错处理,带缩放 dei control data flow: 2> sclr 8168中支持缩放按比例的分子和分母,只支持缩小,貌似不支持放大,且注意输出 ...
- 01-Java学习笔记
本系列笔记由常彦博整理,请知悉 目 录 一. Java技术基础.................................................................... ...
- 域名解析 URL转发
URL转发 转发功能:如果您没有一台独立的服务器(也就是没有一个独立的IP地址)或者您还有一个域名B,您想访问A域名时访问到B域名的内容,这时您就可以通过URL转发来实现.url转发可以转发到某一个目 ...
- 微信小程序demo豆瓣图书
最近微信小程序被炒得很火热,本人也抱着试一试的态度下载了微信web开发者工具,开发工具比较简洁,功能相对比较少,个性化设置也没有.了解完开发工具之后,顺便看了一下小程序的官方开发文档,大概了解了小程序 ...
- Mysql 复制表结构 及其表的内容
顺便转一下Mysql复制表结构.表数据的方法: 1.复制表结构及数据到新表CREATE TABLE 新表 SELECT * FROM 旧表 这种方法会将oldtable中所有的内容都拷贝过来,当然我们 ...