zoukankan      html  css  js  c++  java
  • POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    题意分析

    给出n个点,m个询问,和当前位置pos。
    先给出n-1条边,u->v以及边权w。
    然后有m个询问,询问分2种:
    一是讲第i条边的边权修改为w。
    二是询问从当前位置走到点x经过的边权和(下次询问就是从这点开始)。

    边权的树链剖分,其实和点权的差不多。对于一条边u-v,及其边权w,在建立线段树的时候,将深度大的点,当做其边权w,如dep[u]>dep[v],就令newid[u] = w。这样一来,将边权问题转化为点权问题,需要注意的,就是在查询的时候,对于lca的处理。

    处理方法也很简单,首先判断:当深度大的网上爬,爬到一定程度的时候,是否两点已经重合,若是的话,直接返回值就好。 否则,就用查询[深度小的儿子]到[深度大的这段区间],并将结果累加到ans中。

    代码总览

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll int
    #define nmax 100820
    using namespace std;
    int fa[nmax],son[nmax],sz[nmax],newid[nmax],hashback[nmax],dep[nmax],top[nmax];
    int num,tot,head[nmax];
    struct edge{
        int to;
        int next;
    }edg[nmax<<1];
    struct tree{
        int l,r,val;
        int mid(){
            return (l+r)>>1;
        }
    }tree[nmax<<2];
    struct mess{
        int u,v,w;
    }mes[nmax];
    void add(int u, int v){
        edg[tot].to = v;
        edg[tot].next = head[u];
        head[u] = tot++;
    }
    void dfsFirst(int rt, int f,int d){
        dep[rt] = d;
        fa[rt] = f;
        sz[rt] = 1;
        for(int i = head[rt]; i!= -1; i = edg[i].next){
            int nxt = edg[i].to;
            if(nxt != f){
                dfsFirst(nxt,rt,d+1);
                sz[rt]+=sz[nxt];
                if(son[rt] == -1 || sz[nxt] > sz[son[rt]]){
                    son[rt] = nxt;
                }
            }
    
        }
    }
    void dfsSecond(int rt, int tp){
        top[rt] = tp;
        newid[rt] = ++num;
        if(son[rt] == -1) return;
        dfsSecond(son[rt],tp);
        for(int i = head[rt];i != -1; i = edg[i].next){
            int nxt = edg[i].to;
            if(nxt != son[rt] && nxt != fa[rt])
                dfsSecond(nxt,nxt);
        }
    }
    void init(){
        memset(tree,0,sizeof tree);
        memset(head,-1,sizeof head);
        memset(son,-1,sizeof son);
        memset(edg,0,sizeof edg);
        tot = num = 0;
    }
    void PushUp(int rt){
        tree[rt].val = tree[rt<<1].val + tree[rt<<1|1].val;
    }
    void Build(int l, int r, int rt){
        tree[rt].l = l; tree[rt].r = r;
        if(l == r){
            return;
        }
        Build(l,tree[rt].mid(),rt<<1);
        Build(tree[rt].mid()+1,r,rt<<1|1);
        PushUp(rt);
    }
    void UpdatePoint(int val, int pos, int rt){
        if(tree[rt].l == tree[rt].r){
            tree[rt].val = val ;
            return;
        }
        if(pos <= tree[rt].mid()) UpdatePoint(val,pos,rt<<1);
        else UpdatePoint(val,pos,rt<<1|1);
        PushUp(rt);
    }
    int QuerySUM(int l,int r,int rt)
    {;
        if(l>tree[rt].r || r<tree[rt].l) return 0;
        if(l <= tree[rt].l && tree[rt].r <= r) return tree[rt].val;
        return QuerySUM(l,r,rt<<1) + QuerySUM(l,r,rt<<1|1);
    }
    long long  Find_SUM(int x, int y){
        int tx = top[x],ty =top[y];
        long long ans  = 0;
        while(tx != ty){
            if(dep[tx] < dep[ty]){
                swap(x,y);
                swap(tx,ty);
            }
            ans += QuerySUM(newid[tx],newid[x],1);
            x = fa[tx]; tx = top[x];
        }
        if(x == y) return ans;
        if(dep[x] > dep[y]) swap(x,y);
        ans += QuerySUM(newid[son[x]],newid[y],1);
        return ans;
    }
    
    int n,m;
    int main()
    {
    //    freopen("in.txt","r",stdin);
        int m,x,y,posnow;
        int op;
        while(scanf("%d %d %d",&n,&m,&posnow)!=EOF){
            init();
            for(int i =1;i<=n-1;++i){
                scanf("%d %d %d",&mes[i].u,&mes[i].v,&mes[i].w);
                add(mes[i].u,mes[i].v);
                add(mes[i].v,mes[i].u);
            }
            num = 0;
            dfsFirst(1,0,1);
            dfsSecond(1,1);
            Build(1,n,1);
            for(int i = 1;i<=n-1;++i){
                if(dep[mes[i].u] > dep[mes[i].v])// v is bigger;
                    swap(mes[i].u,mes[i].v);
                UpdatePoint(mes[i].w,newid[mes[i].v],1);
    
            }
    //        printf("MESSA ID    DATA   FA   SON   SIZE   DEEP   NEWID  TOP  SEGHASH
    ");
    //        for(int i = 1;i<=n;++i){
    //            printf("DEBUG %5d %5d %5d %5d %5d %5d %5d %5d %5d
    ",i,data[i],fa[i],son[i],sz[i],dep[i],newid[i],top[i],seghash[i]);
    //        }
    //
    //        printf("MESSA ID   val
    ");
    //        for(int i = 1;i<=n;++i){
    //            printf("DEBUF %d   %d
    ",i,QuerySUM(i,i,1));
    //        }
            for(int i = 0;i<m;++i){
                scanf("%d",&op);
                if(op == 1){//change
                    scanf("%d %d",&x,&y);
                    x = newid[mes[x].v];
                    UpdatePoint(y,x,1);
                }else {//ask
                    scanf("%d",&x);
                    printf("%lld
    ",Find_SUM(posnow,x));
                    posnow = x;
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    团队冲刺2---个人工作总结一(5.25)
    第十二周学习进度
    课堂作业——找水王
    个人冲刺07
    第十五周学习进度情况
    构建之法阅读笔记06
    构建之法阅读笔记05
    第十四周学习进度情况
    个人冲刺06
    个人冲刺05
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367014.html
Copyright © 2011-2022 走看看