poj 2763 Housewife Wind 动态求树上两点之间距离
2015-10-13 14:52
429 查看
题意:
给一棵n<100000个节点的树,和q<100000个操作,每个操作可以将一条边的权改变或者查询树中两点之间的距离。
分析:
首先用dfs将树序列化,然后用rmq求lca,用树状数组求树上两点之间的距离和更新边。
代码:
给一棵n<100000个节点的树,和q<100000个操作,每个操作可以将一条边的权改变或者查询树中两点之间的距离。
分析:
首先用dfs将树序列化,然后用rmq求lca,用树状数组求树上两点之间的距离和更新边。
代码:
//poj 2763 //sep9 #include <iostream> #include <cmath> using namespace std; const int MAXN=100024; const int LOG_MAXN=20; struct EDGE{ int idx,v,w,nxt; }edge[MAXN*2]; struct BIT { int c[MAXN*2],n; void clear(){ memset(c,0,sizeof(c)); } int lowbit(int x){ return x&(x^(x-1)); } void modify(int i,int d){ while(i<=n){ c[i]+=d; i+=lowbit(i); } } int q(int i){ if(i==0) return 0; int sum; for(sum=0;i>0;i-=lowbit(i)) sum+=c[i]; return sum; } }bit; int n,q,s,e; int head[MAXN]; int vs[MAXN*2]; int depth[MAXN*2]; int idx[MAXN]; int es[MAXN*2]; int dis[MAXN*2]; int ST[MAXN*2][LOG_MAXN],ST_IDX[MAXN*2][LOG_MAXN]; void dfs(int u,int p,int d,int &k) { idx[u]=k; vs[k]=u; depth[k++]=d; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].v; if(v!=p){ bit.modify(k,edge[i].w); dis[edge[i].idx*2]=edge[i].w; es[edge[i].idx*2]=k; dfs(v,u,d+1,k); vs[k]=u; depth[k]=d; bit.modify(k,-edge[i].w); es[edge[i].idx*2+1]=k++; } } } void rmq_init(int a[],int lenth) { for(int i=0;i<lenth;++i){ ST[i][0]=a[i]; ST_IDX[i][0]=i; } for(int j=1;(1<<j)<=lenth;++j) for(int i=0;i+(1<<j)<=lenth;++i){ ST[i][j]=ST[i][j-1]; ST_IDX[i][j]=ST_IDX[i][j-1]; if(ST[i+(1<<(j-1))][j-1]<ST[i][j]){ ST[i][j]=ST[i+(1<<(j-1))][j-1]; ST_IDX[i][j]=ST_IDX[i+(1<<(j-1))][j-1]; } } } int query(int l,int r)//[] { int k=(int)(log(r-l+1.0)/log(2.0)); if(ST[l][k]<=ST[r-(1<<k)+1][k]) return ST_IDX[l][k]; return ST_IDX[r-(1<<k)+1][k]; } void init() { bit.clear(); bit.n=2*n; int k=0; dfs(1,-1,0,k); rmq_init(depth,2*n-1); } int lca(int a,int b) { return vs[query(min(idx[a],idx[b]),max(idx[a],idx[b]))]; } int main() { scanf("%d%d%d",&n,&q,&s); e=0; memset(head,-1,sizeof(head)); for(int i=0;i<n-1;++i){ int u,v,w; scanf("%d%d%d",&u,&v,&w); edge[e].idx=i,edge[e].v=v,edge[e].w=w,edge[e].nxt=head[u],head[u]=e++; edge[e].idx=i,edge[e].v=u,edge[e].w=w,edge[e].nxt=head[v],head[v]=e++; } init(); while(q--){ int type; scanf("%d",&type); if(type==0){ int x; scanf("%d",&x); int p=lca(s,x); printf("%d\n",bit.q(idx[s])+bit.q(idx[x])-2*bit.q(idx[p])); s=x; }else{ int x,y; scanf("%d%d",&x,&y); int k=x-1; bit.modify(es[k*2],y-dis[k*2]); bit.modify(es[k*2+1],dis[k*2]-y); dis[k*2]=y; } } return 0; }
相关文章推荐
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析
- C#获取关键字附近文字算法实例