POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)
题意:有一棵树,每条边给定初始权值。一个人从s点出发。支持两种操作:修改一条边的权值;求从当前位置到点u的最短路径。
分析:就是在边可以修改的情况下求树上最短路。如果不带修改的话,用RMQ预处理LCA即可。
在静态版本的LCA问题上,用树状数组维护一条边在dfs序中表示的一段区间。为什么是一段区间,因为求该边之下的任意一点到根节点的距离都必须经过这条边。
用树状数组差分前缀和的方式维护区间修改。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 100005
struct Edge{
int to,next,id;
}edge[maxn<<]; int n,a[maxn],head[maxn],dep[maxn<<],cnt,pos[maxn],dfs_seq[maxn<<],dfn,f[maxn<<][];
int W[maxn],L[maxn],R[maxn],dfs_clock,C[maxn],G[maxn]; inline void add(int u,int v,int id)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
edge[cnt].id=id;
head[u]=cnt++;
} inline int lowbit(int x){return (x)&(-x);} void init()
{
memset(head,-,sizeof(head));
memset(pos,-,sizeof(pos));
memset(C,,sizeof(C));
cnt=dfn=;
dfs_clock=;
} void dfs(int u,int deep)
{
dfs_seq[dfn]=u,dep[dfn]=deep,pos[u]=dfn++;
L[u]=++dfs_clock;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(pos[v]==-){
G[edge[i].id]=v;
dfs(v,deep+);
dfs_seq[dfn]=u,dep[dfn++]=deep;
}
}
R[u]=dfs_clock;
} void init_RMQ(int n)
{
for(int i=;i<=n;++i) f[i][]=i;
for(int j=;(<<j)<=n;++j)
for(int i=;i+(<<j)-<=n;++i){
if(dep[f[i][j-]]<dep[f[i+(<<(j-))][j-]]) f[i][j]=f[i][j-];
else f[i][j]=f[i+(<<(j-))][j-];
}
} inline int RMQ(int L,int R)
{
int k=;
while(<<(k+)<=R-L+) ++k;
if(dep[f[L][k]]<dep[f[R-(<<k)+][k]]) return f[L][k];
return f[R-(<<k)+][k];
} inline int lca(int u,int v)
{
if(pos[u]>pos[v]) return dfs_seq[RMQ(pos[v],pos[u])];
return dfs_seq[RMQ(pos[u],pos[v])];
} inline void update(int i,int x)
{
for(;i<=n;i+=lowbit(i)) C[i]+=x;
} inline int sum(int i)
{
int s=;
for(;i>;i-=lowbit(i)) s+=C[i];
return s;
} int main()
{
int i,u,v,k,q,w,s;
while(~scanf("%d%d%d",&n,&q,&s)){
init();
for(i=;i<n;++i){
scanf("%d%d%d",&u,&v,&w);
add(u,v,i);
add(v,u,i);
W[i]=w;
}
dfs(,);
init_RMQ(dfn-);
u=s; for(i=;i<n;++i){
update(L[G[i]],W[i]);
update(R[G[i]]+,-W[i]);
} while(q--){
scanf("%d",&k);
if(k){
scanf("%d%d",&u,&w);
update(L[G[u]],w-W[u]);
update(R[G[u]]+,-w+W[u]);
W[u]=w;
}
else{
scanf("%d",&v);
printf("%d\n",sum(L[s])+sum(L[v])-*sum(L[lca(s,v)]));
s=v;
}
}
}
return ;
}
树链剖分的方法也类似。剖出轻重链之后,可以快速求解lca,并用树状数组维护边的信息,同样是用差分的方式。
通常树链剖分维护的是树上点的信息,但本题可以用每条边在dfs树上的后继点来表示该边。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn =1e5+;
struct Edge{
int to,next;
}E[*maxn];
int n,head[maxn],tot;
int idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],l[maxn],r[maxn];
int edge[maxn][];
int bit[maxn]; void init()
{
idx=tot=;
memset(head,-,sizeof(head));
dep[]=,fa[]=,size[]=;
memset(son,,sizeof(son));
}
void AddEdge(int u,int v)
{
E[tot] = (Edge){v,head[u]};
head[u]=tot++;
}
void dfs1(int u)
{
size[u]=;
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
} void dfs2(int u,int topu)
{
top[u]= topu;
l[u] = ++idx;
if(son[u]) dfs2(son[u],top[u]);
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
r[u] = idx;
} void add(int pos,int val){
for(int i=pos;i<=n;i+= i&(-i)) bit[i]+=val;
} inline int sum(int pos){
int res=;
for(int i=pos;i;i-= i&(-i)) res+=bit[i];
return res;
} int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u = fa[top[u]];
}
return dep[u]<dep[v] ? u:v;
} int dist(int u,int v){
return sum(l[u])+sum(l[v]) - *sum(l[lca(u,v)]);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int q,s,op,u,v,w;
while(scanf("%d%d%d",&n,&q,&s)==){
init();
memset(bit,,sizeof(bit));
for(int i=;i<n;++i){
scanf("%d%d%d",&u,&v,&w);
AddEdge(u,v);
AddEdge(v,u);
edge[i][] = u,edge[i][] =v,edge[i][] =w;
}
dfs1();
dfs2(,);
for(int i=;i<n;++i){
if(dep[edge[i][]]>dep[edge[i][]]) swap(edge[i][],edge[i][]);
v = edge[i][];
add(l[v],edge[i][]);
add(r[v]+,-edge[i][]);
} while(q--){
scanf("%d",&op);
if(op==){
scanf("%d",&u);
printf("%d\n",dist(s,u));
s = u;
}
else{
int k;
scanf("%d%d",&k,&w);
v = edge[k][];
add(l[v],w-edge[k][]);
add(r[v]+,-w+edge[k][]);
edge[k][] =w;
}
}
}
return ;
}
POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)的更多相关文章
- POJ 2763 Housewife Wind(DFS序+LCA+树状数组)
Housewife Wind Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 11419 Accepted: 3140 D ...
- Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...
- HDU5266 LCA 树链剖分LCA 线段树
HDU5266 LCA Description 给一棵 n 个点的树,Q 个询问 [L,R] : 求点 L , 点 L+1 , 点 L+2 -- 点 R 的 LCA. Input 多组数据. The ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- poj 2763 Housewife Wind(树链拆分)
id=2763" target="_blank" style="">题目链接:poj 2763 Housewife Wind 题目大意:给定一棵 ...
- POJ 2763 Housewife Wind LCA转RMQ+时间戳+线段树成段更新
题目来源:POJ 2763 Housewife Wind 题意:给你一棵树 2种操作0 x 求当前点到x的最短路 然后当前的位置为x; 1 i x 将第i条边的权值置为x 思路:树上两点u, v距离为 ...
- poj 3237 Tree(树链剖分,线段树)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 7268 Accepted: 1969 Description ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- [luogu4886] 快递员(点分治,树链剖分,lca)
dwq推的火题啊. 这题应该不算是点分治,但是用的点分治的思想. 每次找重心,算出每一对询问的答案找到答案最大值,考虑移动答案点,使得最大值减小. 由于这些点一定不能在u的两颗不同的子树里,否则你怎么 ...
随机推荐
- jsp页面form表单提交时候乱码
1.问题描述: 表单提交中文乱码问题,怎么解决 2.原因 当表单传输到服务器上时,服务器会将传输的数据进行编码(iso-8859-1),然后当我们从服务器上面取数据的时候,就会出现乱码 3.解决的方式 ...
- Java技术学习路线图
一:常见模式与工具 学习Java技术体系,设计模式,流行的框架与组件是必不可少的: 常见的设计模式,编码必备 Spring5,做应用必不可少的最新框架 MyBatis,玩数据库必不可少的组件 二:工程 ...
- 第二百三十四节,Bootstrap表单和图片
Bootstrap表单和图片 学习要点: 1.表单 2.图片 本节课我们主要学习一下 Bootstrap 表单和图片功能,通过内置的 CSS 定义,显示各 种丰富的效果. 一.表单 Bootstrap ...
- 日历类Calendar
在早期的JDK版本中,日期(Date)类附有两大功能:(1)允许用年.月.日.时.分.秒来解释日期:(2)允许对表示日期的字符串进行格式化和句法分析.在JDK1.1中提供了类Calendar来完成第一 ...
- Apollo 刨析:简介
Apollo是配置在IIS服务器上的一个Web站点,它使用了.NET4.0和ASP.Net的技术. 代码是C#编写的.是基于ASP.NET MVC3的Web开发框架上编写的一个应用. 它使用到了N ...
- npm install 不自动生成 package-lock.json文件
package-lock.json这个文件的作用就不详细说明了 有需要的可以参考 :https://www.cnblogs.com/cangqinglang/p/8336754.html 网上都说 n ...
- CSS样式设置
转载来自:http://www.imooc.com/article/2067水平居中设置-行内元素 水平居中 如果被设置元素为文本.图片等行内元素时,水平居中是通过给父元素设置 text-align: ...
- DICOM:docker实现DICOM服务虚拟化
背景: docker,是一个开源的应用容器引擎,眼下大多应用在部署和运维领域,然而因为全然使用沙箱机制,相互之间能够看做独立的主机,且自身对资源的需求也十分有限.远远低于虚拟机.甚至非常多时候.能够直 ...
- 初步了解 cURL
今天需要用PHP模拟post请求,查了查资料,了解到cURL.看了一篇博客,写的很详细,就转载了,与大家分享.[原文链接] 什么是cURL?可能还有很多同学没有听说过这个工具,我先来给大家简单介绍下什 ...
- 用pypy运行ryu
最近看到pypy可以提高python的运行速率到很变态的境地,加之现在ryu发现拓扑的能力有限,不能满足实验要求,所以想将其试着在pypy上运行 部署pypy在virtualenv,在学python初 ...