poj 2763 Housewife Wind 树链剖分+LCA
2015-07-11 17:22
429 查看
对于每组询问,我们直接用logn的复杂度求出两个点的LCA,至于修改边以及查询长度则是树链剖分模板题。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #define maxn 100005 using namespace std; int top[maxn],fa[maxn],son[maxn],size[maxn],id[maxn],num,dep[maxn],tot; struct pppi{ int to; int next; }pp2[2*maxn]; int head[maxn]; vector<int >g[maxn]; void add(int u,int v){ pp2[tot].to=v; pp2[tot].next=head[u]; head[u]=tot++; pp2[tot].to=u; pp2[tot].next=head[v]; head[v]=tot++; } struct ppi{ int from; int to; int cost; }pp1[maxn]; struct pi{ int le,ri; int sum; }pp[4*maxn]; void build(int tot,int l,int r){ pp[tot].sum=0; pp[tot].le=l; pp[tot].ri=r; if(l==r) return ; build(2*tot,l,(l+r)/2); build(2*tot+1,(l+r)/2+1,r); } void merg(int tot,int l,int k){ if(pp[tot].ri==pp[tot].le){ pp[tot].sum=k; return ; } int mid; mid=(pp[tot].le+pp[tot].ri)/2; if(l<=mid) merg(2*tot,l,k); else merg(2*tot+1,l,k); pp[tot].sum=pp[2*tot].sum+pp[2*tot+1].sum; } int query(int tot,int l,int r){ if(pp[tot].le>=l&&pp[tot].ri<=r){ return pp[tot].sum; } int s=0; int mid=(pp[tot].le+pp[tot].ri)/2; if(l<=mid) s+=query(2*tot,l,r); if(r>mid) s+=query(2*tot+1,l,r); return s; } void dfs1(int u,int pa,int d){ dep[u]=d; size[u]=1; son[u]=0; fa[u]=pa; int k,v; k=head[u]; while(k!=-1){ v=pp2[k].to; if(v==pa){ k=pp2[k].next; continue; } dfs1(v,u,d+1); size[u]+=size[v]; if(size[son[u]]<size[v]) son[u]=v; k=pp2[k].next; } } void dfs2(int u,int pa,int tp){ int k,v; id[u]=num++; top[u]=tp; if(son[u]) dfs2(son[u],u,tp); k=head[u]; while(k!=-1){ v=pp2[k].to; if(v==pa||v==son[u]){ k=pp2[k].next; continue; } dfs2(v,u,v); k=pp2[k].next; } } int get(int u,int v){ int s=0,to1,to2; to1=top[u]; to2=top[v]; while(to1!=to2){ if(dep[to1]<dep[to2]){ swap(to1,to2); swap(u,v); } s+=query(1,id[to1],id[u]); u=fa[to1]; to1=top[u]; } if(u==v) return s; if(dep[u]>dep[v]) swap(u,v); s+=query(1,id[u]+1,id[v]); return s; } int main() { int i,n,m,p,k,s; scanf("%d%d%d",&n,&m,&s); build(1,1,n-1); memset(head,-1,sizeof(head)); tot=0; for(i=1;i<=n-1;i++){ scanf("%d%d%d",&pp1[i].from,&pp1[i].to,&pp1[i].cost); add(pp1[i].from,pp1[i].to); } num=0; dfs1(1,1,1); dfs2(1,1,1); for(i=1;i<n;i++){ if(fa[pp1[i].from]==pp1[i].to){ merg(1,id[pp1[i].from],pp1[i].cost); } else merg(1,id[pp1[i].to],pp1[i].cost); } for(i=0;i<m;i++){ scanf("%d",&p); if(p==0){ scanf("%d",&k); printf("%d\n",get(s,k)); s=k; } else{ scanf("%d%d",&p,&k); if(fa[pp1[p].from]==pp1[p].to) merg(1,id[pp1[p].from],k); else merg(1,id[pp1[p].to],k); } } }
相关文章推荐
- CSS——LESS
- [LeetCode] Populating Next Right Pointers in Each Node
- jq清除html标签
- Ubuntu搭建Note.Js 平台
- StringBuffer类
- [ Javascript ] 内存泄露以及循环引用解析
- js其他异常引发的问题
- HTML中为什么要清除浮动的个人理解
- JS学习2--精简有趣的JS
- HTML中<meta>标签的实例
- css3 web字体记
- 错误:浏览器访问jsp页面,却变成了下载该页面
- 在网页上显示黑客帝国字幕效果
- wordpress利用CSS让每个页面都不一样
- 判断IE版本的HTML语句详解,如:[if lte IE 9]……[endif]
- JavaScript实现对象数组按不同字段排序
- jquery ajax实现省市二级联动
- css3新增属性API
- extjs_11_mvc模式
- 使用JQuery实现手风琴布局