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 ...
随机推荐
- linux下tcpdump命令详解
简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...
- LCS算法思想
LCS问题就是求两个字符串最长公共子串的问题.解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0.然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的 ...
- 【poj】1001
[题目] ExponentiationTime Limit: 500MS Memory Limit: 10000KTotal Submissions: 123707 Accepted: 30202De ...
- WEB程序会话管理--HttpSession和Cookie
WEB应用的会话管理的原理: 由于WEB应用的请求和响应是基于HTTP的,而HTTP由属于无状态的通信协议,只能记录本次请求的信息,因此服务器不会记住这一次的请求和下一次请求的关系.所以会话管理的原理 ...
- jquery 弹出框 showDialog.js具体用法
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABWwAAAImCAIAAABID1T7AAAgAElEQVR4nO3d329c52Hgff1HvPCNLw
- A星算法
没有采用二叉堆算法优化, 学习了几天终于搞除了一个demo, 这个列子如果点击按钮生成的方块大小不正确,可以先设置下预设调成相应的大小 只能上下左右走 using UnityEngine; usi ...
- PyQt4中无边框窗口的移动(拖动)
import sys from PyQt4.QtGui import * from PyQt4.Qt import * from PyQt4.QtCore import * class AboutUs ...
- pyqt QTreeWidget例子学习
# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import * from Py ...
- SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问的解决方案
今天写了一个excel表的导入功能,结果在excel表中的内容导入到页面时报错:SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT ...
- bower安装使用以及git安装
bower需要:node 和 git node安装包下载:http://blog.csdn.net/myan/article/details/2028545 Git安装: 选择第二项:Use Git ...