fzu 2082 过路费(树链剖分,单点更新+区间求和)
来源:互联网 发布:企业级的数据基础平台 编辑:程序博客网 时间:2024/04/30 19:09
题目:http://vjudge.net/contest/28982#problem/G
题意:
有n座城市,由n-1条路相连通,使得任意两座城市之间可达。每条路有过路费,要交过路费才能通过。每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费。
分析:
树链剖分,基于边的重编号
操作:单点更新,区间求和
用树状数组或者线段树维护操作
代码:
#include <cstdio>#include <algorithm>#include <iostream>#include <string.h>using namespace std;const int N = 50010;struct EDGE { int v,nex;} edge[N<<1];int head[N],tot;int dep[N],p[N],fa[N],top[N],son[N],siz[N];int cnt,c[N];void addedge(int a,int b) { edge[tot].v=b; edge[tot].nex=head[a]; head[a]=tot++;}void dfs(int u) { siz[u]=1,son[u]=0; for(int i=head[u]; ~i; i=edge[i].nex) { int v=edge[i].v; if(v!=fa[u]) { fa[v]=u; dep[v]=dep[u]+1; dfs(v); if(siz[v]>siz[son[u]])son[u]=v; siz[u]+=siz[v]; } }}void build(int u,int tp) { p[u]=++cnt; top[u]=tp; if(son[u])build(son[u],tp); for(int i=head[u]; ~i; i=edge[i].nex) { int v=edge[i].v; if(v!=son[u]&&v!=fa[u])build(v,v); }}//树状数组int lowbit(int x) { return x&(-x);}int getsum(int x) { int res=0; while(x)res+=c[x],x-=lowbit(x); return res;}void add(int x,int v) { while(x<N)c[x]+=v,x+=lowbit(x);}int query(int x,int y) { return getsum(y)-getsum(x-1);}int find(int a,int b) { int f1=top[a],f2=top[b],tmp=0; while(f1!=f2) { if(dep[f1]<dep[f2])swap(f1,f2),swap(a,b); tmp+=query(p[f1],p[a]); a=fa[f1],f1=top[a]; } if(a==b)return tmp; if(dep[a]>dep[b])swap(a,b); return tmp+query(p[son[a]],p[b]);}int n,u,v,ww,m,op,d[N][3];int main() { int T; //freopen("f.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { int root=1; fa[root]=dep[root]=cnt=tot=0; memset(siz,0,sizeof(siz)); memset(head,-1,sizeof(head)); memset(c,0,sizeof(c)); for(int i=1; i<n; i++) { scanf("%d%d%d",&u,&v,&ww); addedge(u,v); addedge(v,u); d[i][0]=u; d[i][1]=v; d[i][2]=ww; } dfs(root); build(root,root); for(int i=1; i<n; i++) { if(dep[d[i][0]]>dep[d[i][1]])swap(d[i][0],d[i][1]); add(p[d[i][1]],d[i][2]); } while(m--) { scanf("%d",&op); int a,b; scanf("%d%d",&a,&b); if(op==1)printf("%d\n",find(a,b)); else { add(p[d[a][1]],-d[a][2]); add(p[d[a][1]],b); d[a][2]=b; } } } return 0;}
线段树:
#include <cstdio>#include <algorithm>#include <iostream>#include <string.h>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int N = 50010;struct EDGE { int v,nex;} edge[N<<1];int head[N],tot;int dep[N],p[N],fa[N],top[N],son[N],siz[N];int cnt,sum[N<<1];void addedge(int a,int b) { edge[tot].v=b; edge[tot].nex=head[a]; head[a]=tot++;}void dfs(int u) { siz[u]=1,son[u]=0; for(int i=head[u]; ~i; i=edge[i].nex) { int v=edge[i].v; if(v!=fa[u]) { fa[v]=u; dep[v]=dep[u]+1; dfs(v); if(siz[v]>siz[son[u]])son[u]=v; siz[u]+=siz[v]; } }}void build(int u,int tp) { p[u]=++cnt; top[u]=tp; if(son[u])build(son[u],tp); for(int i=head[u]; ~i; i=edge[i].nex) { int v=edge[i].v; if(v!=son[u]&&v!=fa[u])build(v,v); }}void update(int p,int x,int l,int r,int rt) { if(l==r) { sum[rt]=x; return; } int m=l+r>>1; if(p<=m)update(p,x,lson); else update(p,x,rson); sum[rt]=sum[rt<<1]+sum[rt<<1|1];}int query(int a,int b,int l,int r,int rt) { if(a<=l&&r<=b)return sum[rt]; int m=l+r>>1; int ret=0; if(a<=m)ret+=query(a,b,lson); if(b>m)ret+=query(a,b,rson); return ret;}int find(int a,int b) { int f1=top[a],f2=top[b],tmp=0; while(f1!=f2) { if(dep[f1]<dep[f2])swap(f1,f2),swap(a,b); tmp+=query(p[f1],p[a],1,cnt,1); a=fa[f1],f1=top[a]; } if(a==b)return tmp; if(dep[a]>dep[b])swap(a,b); return tmp+query(p[son[a]],p[b],1,cnt,1);}int n,u,v,ww,m,op,d[N][3];int main() { int T; //freopen("f.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { int root=1; fa[root]=dep[root]=cnt=tot=0; memset(siz,0,sizeof(siz)); memset(head,-1,sizeof(head)); memset(sum,0,sizeof(sum)); for(int i=1; i<n; i++) { scanf("%d%d%d",&u,&v,&ww); addedge(u,v); addedge(v,u); d[i][0]=u; d[i][1]=v; d[i][2]=ww; } dfs(root); build(root,root); for(int i=1; i<n; i++) { if(dep[d[i][0]]>dep[d[i][1]])swap(d[i][0],d[i][1]); update(p[d[i][1]],d[i][2],1,cnt,1); } while(m--) { scanf("%d",&op); int a,b; scanf("%d%d",&a,&b); if(op==1)printf("%d\n",find(a,b)); else update(p[d[a][1]],b,1,cnt,1); } } return 0;}
0 0
- fzu 2082 过路费(树链剖分,单点更新+区间求和)
- 【树链剖分】FZU 2082 过路费 求和
- FZU 2082 过路费(树链剖分)
- fzu 2082 过路费(树链剖分)
- FZU 2082 过路费 (树链剖分)
- FZU 2082 过路费(树链剖分)
- 【树链剖分】 FZU 2082 过路费
- fzu 2082 过路费(树链剖分)
- FZU 2082 过路费 (树链剖分)
- FZU 2082 过路费 树链剖分
- FZU 2082过路费 树链剖分
- FZU 2082 过路费 [树链剖分]
- HYSBZ 1036 树链剖分(单点更新区间求和求最大值)
- 线段树(单点更新,区间求和)
- FZU 2082 过路费 (树链剖分)边权
- FZU 2082 过路费(树链剖分+BIT)
- FZU 2082 过路费(树链剖分,边权)
- hdu1166单点更新,区间求和
- centos yum配置
- HDU#1215:七夕节
- MySQL客户端工具推荐
- Eclipse背景颜色修改
- 非模式窗体从创建到销毁都需要代码来维护,防止内存未安全释放
- fzu 2082 过路费(树链剖分,单点更新+区间求和)
- C#中对byte类型的处理还是很特殊的。
- POJ2389 FFT 大数乘法
- Mysql 常用函数总结(其他函数)
- 微信公众号【客服接口】
- iOS NSFileHandle详解
- 简单理解struts中的ValueStack(VS)+实例
- OkHttp基本使用方式
- 临时保存文件