zoukankan      html  css  js  c++  java
  • 树链剖分——边权poj2763

    边权操作起来也和点权一样,只要把边的权值映射到点上即可,要注意的地方是向上爬的过程中和点权不太一样,还有个特判(WA了几次。。)

    完整代码

    #include<cstring>
    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define maxn 100005
    struct E{int x,y;}e[maxn];
    struct Edge{int to,nxt,w;}edge[maxn<<1];
    int head[maxn],tot,v[maxn],n,q,c;
    void init(){memset(head,-1,sizeof head);tot=0;}
    void addedge(int u,int v,int w){
        edge[tot].to=v;edge[tot].w=w;edge[tot].nxt=head[u];head[u]=tot++;
    }
    int f[maxn],son[maxn],d[maxn],size[maxn];
    void dfs1(int x,int pre,int deep){
        size[x]=1,d[x]=deep,f[x]=pre;
        for(int i=head[x];i!=-1;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==pre)continue;
            v[y]=edge[i].w;//注意这里将边权映射到点上 
            dfs1(y,x,deep+1);
            size[x]+=size[y];
            if(size[y]>size[son[x]])son[x]=y;
        }
    }
    int cnt,top[maxn],id[maxn],rk[maxn];
    void dfs2(int x,int tp){
        top[x]=tp;id[x]=++cnt;rk[cnt]=x;
        if(son[x])dfs2(son[x],tp);
        for(int i=head[x];i!=-1;i=edge[i].nxt){
            int y=edge[i].to;
            if(y!=f[x] && y!=son[x])dfs2(y,y);
        }
    }
    
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    int sum[maxn<<2];
    void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
    void build(int l,int r,int rt){
        if(l==r){sum[rt]=v[rk[l]];return;}
        int m=l+r>>1;
        build(lson);build(rson);
        pushup(rt);
    }
    void update(int pos,int l,int r,int rt,int v){
        if(l==r){sum[rt]=v;return;}
        int m=l+r>>1;
        if(pos<=m)update(pos,lson,v);
        else update(pos,rson,v);
        pushup(rt);
    }
    int query(int L,int R,int l,int r,int rt){
        if(L<=l && R>=r)return sum[rt];
        int m=l+r>>1,res=0;
        if(L<=m)res+=query(L,R,lson);
        if(R>m)res+=query(L,R,rson);
        return res; 
    }
    
    int Query(int x,int y){
        int res=0;
        while(top[x]!=top[y]){
            if(d[top[x]]<d[top[y]])swap(x,y);
            res+=query(id[top[x]],id[x],1,n,1);
            x=f[top[x]];
        } 
        if(x==y)return res;
        if(id[x]>id[y])swap(x,y);
        return res+query(id[son[x]],id[y],1,n,1);
    }
    
    int main(){
        init();int s;
        scanf("%d%d%d",&n,&q,&s);
        for(int i=1;i<n;i++){
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            e[i].x=x;e[i].y=y;
            addedge(x,y,z);addedge(y,x,z);
        }
        cnt=0;dfs1(s,0,1);dfs2(s,s);
        build(1,n,1);
        while(q--){
            int op,x,y;
            scanf("%d",&op);
            if(op==0){scanf("%d",&x);
                cout<<Query(s,x)<<'
    ';s=x;}
            if(op==1){
                scanf("%d%d",&x,&y);
                int u=e[x].x,v=e[x].y;
                if(d[u]<d[v])swap(u,v);
                update(id[u],1,n,1,y);
            }
        }
    }
    View Code

    不同之处:最后一次查询的时候不要最高的那个点权

    特判:x==y的时候直接返回即可

    int Query(int x,int y){
        int res=0;
        while(top[x]!=top[y]){
            if(d[top[x]]<d[top[y]])swap(x,y);
            res+=query(id[top[x]],id[x],1,n,1);
            x=f[top[x]];
        } 
        if(x==y)return res;
        if(id[x]>id[y])swap(x,y);
        return res+query(id[son[x]],id[y],1,n,1);
    }
  • 相关阅读:
    SqlServer查询优化方法
    关于导入excel问题
    修改SQL数据库中表字段类型时,报“一个或多个对象访问此列”错误的解决方法
    软件架构之我见
    算法-插入排序
    算法-快速排序
    WCF系列 Restful WCF
    WCF系列 基础概念
    cocos2dx-是男人就坚持20s 练手项目
    nodejs 聊天室简单实现
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10755760.html
Copyright © 2011-2022 走看看