POJ 2763 Housewife Wind 树链剖分模板

时空隧道


题目大意:
一棵树,两种操作:①改变第x条边的权值②询问x到y的路径长度


分析:
树链剖分模板
(自认为代码写的还是比较好看滴….QAQ


代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;
const int maxn=100000+5;
int n,S,q,hd[maxn],to[maxn*2],nxt[maxn*2],w[maxn*2],cnt,val[maxn],dep[maxn],fa[maxn],son[maxn],top[maxn],size[maxn]; 
struct edge{
    int s,x,y;
}e[maxn];
struct Tree{
    int l,r,sum;
}tree[maxn*4];
inline void add(int x,int y){
    to[cnt]=y;
    nxt[cnt]=hd[x];
    hd[x]=cnt++;
}
inline void dfs1(int root,int f){
    size[root]=1;
    for(int i=hd[root];i!=-1;i=nxt[i])
        if(to[i]!=f){
            fa[to[i]]=root;
            dep[to[i]]=dep[root]+1;dfs1(to[i],root);
            size[root]+=size[to[i]];
            if(son[root]==-1||size[to[i]]>size[son[root]])
                son[root]=to[i];
        }
}
inline void dfs2(int root,int f){
    w[root]=++cnt,top[root]=f;
    if(son[root]==-1)
        return;
    dfs2(son[root],f);
    for(int i=hd[root];i!=-1;i=nxt[i])
        if(to[i]!=fa[root]&&to[i]!=son[root])
            dfs2(to[i],to[i]);
}
inline void build(int l,int r,int tr){
    tree[tr].l=l,tree[tr].r=r;
    if(l==r){
        tree[tr].sum=val[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,tr<<1),build(mid+1,r,tr<<1|1);
    tree[tr].sum=tree[tr<<1].sum+tree[tr<<1|1].sum;
}
inline void change(int pos,int VAL,int tr){
    if(tree[tr].l==tree[tr].r){
        tree[tr].sum=VAL;
        return;
    }
    int mid=(tree[tr].l+tree[tr].r)>>1;
    if(pos<=mid)
        change(pos,VAL,tr<<1);
    else
        change(pos,VAL,tr<<1|1);
    tree[tr].sum=tree[tr<<1].sum+tree[tr<<1|1].sum;
}
inline int query(int l,int r,int tr){
    if(tree[tr].l==l&&tree[tr].r==r)
        return tree[tr].sum;
    int mid=(tree[tr].l+tree[tr].r)>>1;
    if(r<=mid)
        return query(l,r,tr<<1);
    else if(l>mid)
        return query(l,r,tr<<1|1);
    else
        return query(l,mid,tr<<1)+query(mid+1,r,tr<<1|1);
}
inline void Change(int id,int VAL){
    if(dep[e[id].x]>dep[e[id].y])
        change(w[e[id].x],VAL,1);
    else
        change(w[e[id].y],VAL,1);
}
inline int Query(int u,int v){
    int ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])
            swap(u,v);
        ans+=query(w[top[u]],w[u],1);
        u=fa[top[u]];
    }
    if(dep[u]>dep[v])
        swap(u,v);
    if(u!=v)
        ans+=query(w[son[u]],w[v],1);
    return ans;
}
signed main(void){
    cnt=0,memset(hd,-1,sizeof(hd));
    memset(son,-1,sizeof(son));
    scanf("%d%d%d",&n,&q,&S);
    for(int i=1,x,y,s;i<n;i++)
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].s),add(e[i].x,e[i].y),add(e[i].y,e[i].x);
    dep[1]=cnt=0;dfs1(1,-1);dfs2(1,1);
    for(int i=1;i<n;i++){
        if(dep[e[i].x]>dep[e[i].y])
            val[w[e[i].x]]=e[i].s;
        else
            val[w[e[i].y]]=e[i].s;
    }
    build(1,n,1);
    int x,y,cmd;
    while(q--){
        scanf("%d%d",&cmd,&x);
        if(cmd==0)
            cout<<Query(S,x)<<endl,S=x;
        else
            scanf("%d",&y),Change(x,y);
    }
    return 0;
}

by >_< NeighThorn

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值